0

I am wondering how to make the GeoJSON search more efficient. I would like to get the search result from more than 1 layer in GeoJSON.

My code is (I attached one of two GeoJSON examples):

var test = [{
"type": "Feature",
             "properties": {
             "Title": "Waterbeach Church",
                 "Head": "Chapel Street",
                 "Description": "Parish community"
        },
            "geometry": {
            "type": "Point",
            "coordinates": [
            0.192763,
            52.263692
                ]
                  }
                    }];

var geojsonMarkerOptions2 = {
radius: 5,
fillColor: "#ffc34d",
color: "#1a1100",
weight: 1,
opacity: 1,
fillOpacity: 0.4
};

var church = L.geoJSON(test, {
pointToLayer: function (feature, latlng) {
    return L.circleMarker(latlng, geojsonMarkerOptions2);
},
    onEachFeature: function (feature, layer) {
        layer.bindPopup('<h1><u><font color="red">'+feature.properties.Title+'</h1></u></font><h2>Address: '+feature.properties.Head+'</h2><p>'+feature.properties.Description+'</p><a>'+feature.properties.URL+'</a>');
}

    }).addTo(map);

Afterwards, I am using Leaflet GeoJSON control search, where I want to search between both multiple geoJSON layers (already solved using this link:

L.Control.Search: Using looping for searching data on Leaflet

and for their property features. I am interested in search for more than 1 properties.

When I place another value in "propertyName", then query is redirected to this 2nd value instead of 1st or both.

L.control.search({
layer: L.layerGroup ([sitis, church]),
initial: false,
propertyName: 'Title', 'Head' // Specify which property is searched into.
  })
  .addTo(map);

Can I have something like: propertyName: L.GeoJSON.PropertyGroup (['Title', 'Head', 'Description]),

Or is there another reasonable solution for this issue?

  • Please add also second GeoJSON example to your question. – TomazicM Aug 2 at 14:33
  • It's exactly the same. The name is only different, but properties are the same: It's not enough space to do it here unfortunately. var sitis = {...GEOJSON file THE SAME feature properties (only different names)...} var GeoJSONMarkerOptions - exactly the same values, only colour and radius slightly different... My GeoJSON properties contains: Title Head Description I would like to have them searchable – Mariusz Krukar Aug 2 at 14:44
  • I was asking for it just to be sure properties are the same in both. – TomazicM Aug 2 at 17:08
1

Answer is based on Leaflet.Control.Search plugin example Search markers with Fuzzy Search, which uses Fuse.js library for searching objects by keywords in properties.

The key steps to make possible search on two properties of two GeoJSON layers are:

  1. At the time of creating GeoJSON layer, define new feature property myKey, which combines both properties we want to search: Title and Head. This property will be used for search and for displaying search suggestions.
  2. Create fuse search object on the basis of concatenated GeoJSON objects. Object are concatenated so that there is only one sorted search list. There are various search options possible. Below example searches beginning of words, with at leat two characters required to start search.
  3. Create searchControl for searching, with filterData option where search is done with the help of fuse search.
var sitis = L.geoJSON(test1, {
  pointToLayer: function (feature, latlng) {
    feature.properties.myKey = feature.properties.Title + ', ' + feature.properties.Head
    return L.circleMarker(latlng, geojsonMarkerOptions2);
  },
  onEachFeature: function (feature, layer) {
    layer.bindPopup('<h1><u><font color="red">'+feature.properties.Title+'</h1></u></font><h2>Address: '+feature.properties.Head+'</h2><p>'+feature.properties.Description+'</p><a>'+feature.properties.URL+'</a>');
  }
}).addTo(map);

var church = L.geoJSON(test2, {
  pointToLayer: function (feature, latlng) {
    feature.properties.myKey = feature.properties.Title + ', ' + feature.properties.Head
    return L.circleMarker(latlng, geojsonMarkerOptions2);
  },
  onEachFeature: function (feature, layer) {
    layer.bindPopup('<h1><u><font color="red">'+feature.properties.Title+'</h1></u></font><h2>Address: '+feature.properties.Head+'</h2><p>'+feature.properties.Description+'</p><a>'+feature.properties.URL+'</a>');
  }
}).addTo(map);

var fuseOptions = {
  shouldSort: true,
  tokenize: true,
  threshold: 0,
  location: 0,
  distance: 100,
  maxPatternLength: 32,
  minMatchCharLength: 2,
  keys: ['properties.myKey']
};

var fuse = new Fuse(test1.features.concat(test2.features), fuseOptions);

var allLayers = L.layerGroup([sitis, church]);

var searchControl = new L.Control.Search({
  layer: allLayers,
  propertyName: 'myKey',
  marker: false,
  filterData: function(text, records) {
    var ret = {}, key;
    var jsons = fuse.search(text);
    for(var i in jsons) {
      key = jsons[i].properties.myKey;
      ret[key]= records[key];
    }
    return ret;
  }
});
  • Hi, Thank you. It works, very similarly to the simple one, however without this code: marker: false, filterData: function(text, records) { var ret = {}, key; var jsons = fuse.search(text); for(var i in jsons) { key = jsons[i].properties.myKey; ret[key]= records[key]; } return ret; } When I add up the code above, then search box is not viable. It looks like still something is missing there. – Mariusz Krukar Aug 5 at 11:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.