How-to Configure “or” type Search¶
Allow any matching field.¶
The following change will match any field. For example, it will match both the OWNER_NAME field and the OWN_ADD_L1 field if they both contain search terms.
In the app.js
configuration after:
app.registerService('search', SearchService, {
fields: [
{type: 'text', label: 'Owner Name', name: 'OWNER_NAME'},
{type: 'text', label: 'Street/Address', name: 'OWN_ADD_L1'},
{type: 'text', label: 'City/State/ZIP', name: 'OWN_ADD_L3'}
],
Add the following:
prepareFields: function (fields) {
// reformat the fields for the query engine,
// "*stuff*" will do a case-ignored "contains" query.
var query = ['or'];
for(var i = 0, ii = fields.length; i < ii; i++) {
if(fields[i].value !== '' && fields[i].value !== undefined) {
query.push({
comparitor: 'ilike',
name: fields[i].name,
value: '%' + fields[i].value + '%'
});
}
}
return [query];
},
Testing in the demo¶
Use ‘Little’ in the ‘Owner Name’ field and ‘Blaine’ in the ‘Street/Address’ field. This should return both parcels with ‘Little’ in the ‘Owner Name’ and who live on ‘Blaine’.
Use a single field to search many¶
Many users are accustomed to search utilities which allow for a single search term to search multiple fields. GeoMoose supports that with the follow change:
app.registerService('search', SearchService, {
// The input fields are defined only using one field
fields: [
{type: 'text', label: 'Search', name: 'TERM'},
],
prepareFields: function (fields) {
// this pulls out the term from the search
const searchTerm = fields[0].value;
// this is the list of fields in the layer which will be searched.
const searchFields = ['OWNER_NAME', 'OWN_ADD_L1', 'OWN_ADD_L2'];
// this switched to matching any field
var query = ['or'];
for(var i = 0, ii = searchFields.length; i < ii; i++) {
query.push({
comparitor: 'ilike',
name: searchFields[i],
value: '%' + searchTerm + '%'
});
}
return [query];
},
searchLayers: ['vector-parcels/parcels'],
validateFieldValues: function (fields) {
let nonEmpty = 0;
const validateFieldValuesResult = {
valid: true,
message: null
};
if (fields['TERM'] !== undefined && fields['TERM'] !== '') {
nonEmpty++;
}
if (nonEmpty === 0) {
validateFieldValuesResult.valid = false;
validateFieldValuesResult.message = 'Please complete at least one field.'
}
return validateFieldValuesResult;
}
});
Testing in the demo¶
Search using the term ‘ant’. There will be owners with ‘ant’ in their name and streets which include ‘ant’ in the street name.
Search with a list¶
There are cases in which using a list of features is easier than using terms. For example, getting a list of parcels from an external application and searching for that list of parcels.
app.registerService('search', SearchService, {
fields: [
{type: 'text', label: 'PINs', name: 'TERM'},
],
prepareFields: function (fields) {
const searchTerm = fields[0].value;
// The replace will clean up any whitespace
// The split converts the list to an array.
const pinList = searchTerm.replace(' ', '').split(',');
// this is the list of fields in the layer which will be searched.
// Warning! Adding a list of fields here can make the search very slow!
const searchFields = ['PIN'];
var query = ['or'];
// search each field with the list of pins.
for (var f = 0, ff = searchFields.length; f < ff; f++) {
for(var i = 0, ii = pinList.length; i < ii; i++) {
query.push({
comparitor: 'eq',
name: searchFields[f],
value: pinList[i]
});
}
}
return [query];
},
searchLayers: ['vector-parcels/parcels']
});
Testing in the demo¶
Search using the following list:
350010001079, 070030004077, 163030001000, 160050008003
.
Searching the kitchen sink¶
The user is presented with a single input box to enter search terms. The search then looks for those terms from a list of attributes using the “ilike” method (which ignores case and matches partial matches).
The code!¶
app.registerService('search', SearchService, {
fields: [
{type: 'text', label: 'Search', name: 'TERM'},
],
prepareFields: function (fields) {
const searchTerm = fields[0].value;
// The replace will clean up any whitespace
// The split converts the list to an array.
const termList = searchTerm.replace(' ', '').split(',');
// this is the list of fields in the layer which will be searched.
// Warning! Adding a list of fields here can make the search very slow!
const searchFields = ['PIN', 'OWNER_NAME', 'OWN_ADD_L1', 'OWN_ADD_L2'];
var query = ['or'];
// search each field with the list of pins.
for (var f = 0, ff = searchFields.length; f < ff; f++) {
for(var i = 0, ii = termList.length; i < ii; i++) {
query.push({
comparitor: 'ilike',
name: searchFields[f],
value: '%' + termList[i] + '%'
});
}
}
return [query];
},
searchLayers: ['vector-parcels/parcels']
});
Testing in the demo¶
This is implemented in the demo as the “Single field search” tool. The following search terms can be used to test the functionality:
peters
peters, 237
thoma, lakevill, hamb