gordie
gordie

Reputation: 1955

mapbox : filter features based on 'tags' property (which is an array)

I have some features that have a tags property, which is an array:

[
  {
    "type": "Feature",
    "properties": {
        "id":1,
        "tags": ["tagA","tagB"]
    }
  },
  {
    "type": "Feature",
    "properties": {
        "id":2,
        "tags": ["tagB","tagE"]
    }
  },
  {
    "type": "Feature",
    "properties": {
        "id":3,
        "tags": ["tagZ","tagF"]
    }
  },
  {
    "type": "Feature",
    "properties": {
        "id":4,
        "tags": ["tagN","tagP"]
    }
  },
  {
    "type": "Feature",
    "properties": {
        "id":5,
        "tags": ["tagY","tagT"]
    }
  }
]

Using a list of allowed tags,

 const allowedTags = ['tagY','tagZ']

...what would be the syntax of a Mapbox layer filter that would get the features having at least one tag from my input (in this example, the feature #3 and #5) ?

I tested this

const tagsFilter = ['in', ['get', 'tags'], ['literal', ['tagY','tagZ']]];
map.setFilter("markers",tagsFilter);

But it does not work. Seems this exact syntax should rather be used to compare a single value, like

const idFilter = ['in', ['get', 'id'], ['literal', [3,5]]];

Thanks !

Upvotes: 1

Views: 1475

Answers (1)

gordie
gordie

Reputation: 1955

I found out thanks to this example:

This would work

['any',
  ['in', 'tagY', ['get', 'tags']],
  ['in', 'tagZ', ['get', 'tags']]
]

I made a function out of it :

function getTagsFilter(tags){

  //no tags set
  if ( (tags || []).length === 0) return;

  //expression for each tag
  const tagFilters = tags.map(tag=>['in',tag,['get', 'tags']])

  return ['any'].concat(tagFilters);

}

const allowedTags = ['tagY','tagZ'];
map.setFilter("markers",getTagsFilter(allowedTags));//yeepee!

Bonus

to rather exclude those tags, just use

map.setFilter("markers",['!',getTagsFilter(disabledTags)]);//yeepee again!

Upvotes: 3

Related Questions