3

One of the tables in one of our Mapbox tilesets has a stringified JSON array property of ids:

"string_ids":"[\"a\",\"b\"]"

I would like to filter features using this property, but can't seem to find a way to do it in the Predicates and Expressions documentation. So, for instance, I'd like to filter features so only those that have a "string_id" of "a" display.

I believe this will help with my problem, when ready (https://github.com/mapbox/mapbox-gl-js/issues/4113), but just wondering if there's another solution in place at this time?

UPDATE

I've tried several different approaches:

  • NSPredicate(format: "'a' IN CAST(string_ids, 'NSArray<NSString>')") errors out with: "Casting expression to NSArray not yet implemented."
  • NSPredicate(format: "string_ids contains[c] %@", "a") does not error out, but no features match the filter.
  • NSPredicate(format: "string_ids LIKE 'a'")errors out with: "NSPredicateOperatorType:7 is not supported."
Nate Irwin
  • 600
  • 1
  • 11
  • 20
  • Would help to see some example code, I don't know what your implementation looks like but it's concerning that you have unparsed json. – emma ray Jun 24 '19 at 13:26
  • Well, there's not much to it. I currently use an NSPredicate to filter features that match a certain condition: `self.basePredicate = NSPredicate(format: "id=5")`. I want to do something similar, but against the `string_ids` property detailed above. – Nate Irwin Jun 25 '19 at 14:32
  • Possible solution — `https://stackoverflow.com/questions/32504186/apply-nspredicate-on-string-arraystring` – RobLabs Sep 06 '19 at 16:02
  • @RobLabs: Unfortunately, that won't work. It looks like I'm blocked until this issue is resolved: https://github.com/mapbox/mapbox-gl-native/issues/11786. The "CONTAINS" string comparison does exactly what I'm looking for, but it is not fully implemented in the Mapbox iOS SDK. – Nate Irwin Sep 09 '19 at 20:55
  • This could work too: https://github.com/mapbox/mapbox-gl-js/pull/6228. But, again, it isn't fully implemented and merged yet. – Nate Irwin Sep 09 '19 at 21:13

2 Answers2

1

NSExpression/NSPredicate implementations vary in terms of which operators are supported. (If you look through Apple’s NSPredicate documentation, there are caveats about certain Core Data backends lacking support for certain operators too.)

The iOS map SDK doesn’t support IN, CONTAINS, and LIKE for strings, among other operators. Under the hood, the SDK translates NSExpressions and NSPredicates to the expression syntax described in the Mapbox Style Specification.

As you noted, the style specification lacks an operator for searching for substrings. It also lacks an operator for splitting a string or for converting a string to a JSON object (no issue yet, but feel free to open one).

One workaround might be to query for features in the source using -[MGLVectorTileSource featuresInSourceLayersWithIdentifiers:predicate:], manually evaluate the property values to whether they should be shown, and add the modified features to a new MGLShapeSource.

Another limitation you may run into is that feature querying results can’t have feature properties set to nested objects and arrays.

Minh Nguyễn
  • 861
  • 7
  • 18
  • Thanks for the response! Bummer this isn't supported, as it seems like a fairly common use case, but I'll work around it for now. I'll also keep an eye on the GitHub issues you linked to to track progress. – Nate Irwin Sep 10 '19 at 15:53
  • Any luck on this? I'm stuck in the same situation. when I use MGLVectorTileSource(identifier: "road", configurationURL: NSURL(string: "mapbox://mapbox.mapbox-streets-v8")! as URL).features(sourceLayerIdentifiers: setString, predicate: nil) it returns an empty array. – Rob.R Oct 01 '19 at 23:37
  • Note that `MGLVectorTileSource.features(sourceLayerIdentifiers:predicate:)` only returns features in tiles that the source has had to load and display so far. So if you call the method right away when the style finishes loading, the source likely won’t have anything to return. – Minh Nguyễn Oct 03 '19 at 08:30
0

As of v5.8.0-alpha.1 of the Mapbox iOS SDK, this is now supported.

So, to close the loop on my original question, this predicate is now working as desired: NSPredicate(format: "string_ids contains 'a'").

Nate Irwin
  • 600
  • 1
  • 11
  • 20