-
Notifications
You must be signed in to change notification settings - Fork 290
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support to parse some or all MVT feature properties as JSON #715
Conversation
@nvkelso I think we also had some values similar to this in TIlezen for awhile (for multiple shields?), but removed them (for unrelated reasons). |
Tilezen still exports the array properties in GeoJSON and TopoJSON, but currently strips out in MVT. We can start exporting them in MVT when Tangram grows support. Primarily these are multishields (road, transit, walk, bike). |
Oh great! Bring it on :) |
@matteblair thoughts on this on the ES side? |
This would be a bigger change for Tangram ES since we currently model feature properties explicitly as a mapping of strings to scalar values. However I can see the value in supporting more structured data for properties. This is also a topic of discussion for the next version of the MVT spec (mapbox/vector-tile-spec#75). It does not seem like the proposed solution in MVT would be mutually exclusive with the one here, but it would make this one redundant. The MVT proposal also has the advantage that it's a much more compact representation of structured data: values can be de-duplicated in MVT but in stringified JSON they must be duplicated. |
I agree the eventual MVT v3 solution will be better, however after some time (that ticket was opened in 2016...) I decided to finally move ahead with this because: 1) there are popular tools that implement this JSON stringify behavior, particularly Tippecanoe, so it's a reality for a lot of existing data, and 2) MVT v3 is going to be a substantial upgrade (tons of other things in the spec) that will require widespread updates to both encoding and decoding libs and I think a lot of MVT v2 data will persist. |
That makes sense. We probably shouldn't count on the MVT v3 spec being finished any time soon, and even with that approach we would have to update the feature data model in Tangram ES. This feature sounds good to me. |
I'm also interested in finding ways to make these properties available to filters in a "native" way, since using a JS function in a filter makes it an order of magnitude slower in Tangram ES. Having built-in accesors for structured properties could also implicitly define which ones need to be parsed, and allow us to do it lazily. |
Agree on finding adding support for more native syntax. I'm mostly concerned about how to do it in a way that doesn't impact performance, since the assumption of a 1:1 mapping from YAML string to feature property key is fast. But I'm sure we can use some clues from data source definition and/or caching strategy to mitigate this. |
assume specified property names can be parsed when using `parse_json: []` form
46ca815
to
2f8f269
Compare
(unescaped '.' will be interpreted as a nested feature property)
OK @matteblair inspired me to take this further. I've added support both for accessing nested properties with native syntax in filters, and for doing array-to-array filter operations. I'm not 100% sure of the syntax/naming decisions here, so feedback/alternatives welcome. Nested properties in filtersDot notation with Given a feature property
Feature property names that include a
These could be mixed, e.g. a property
Array-to-array filtersWe have existing syntax for checking if a single value matches one of a list of values, e.g.: Does value
As part of this new support for "complex" property values that may be arrays, we need to expand this syntax. This branch adds two keywords for this, by extending the same filter object pattern we use for To check if an array
Note: while it would be possible to check the type value of There are also cases where you'd like to test that an array contains all of a list of values. An
One could check for multiple array values with multiple filters, but supporting direct syntax for them would be much more efficient than this, which will execute 3 separate array tests, e.g.:
Note: |
I like the property accesors! Should be both more performant and easier to use for authoring filters. I'd suggest |
An alternative way of accessing nested properties in YAML would be to use arrays for the filter keys, like:
But I don't think this works in the JS YAML model - plus it's not very natural to read. The |
I dig it, and @matteblair suggestion for
For the complicated property names, could we allow that be be quoted like |
@bcamper can you add an example on how to access the multishields in the Will Tangram abstract that GeoJSON and MVT store it in different ways, but I think Tangram will expand the MVT shorthand to the GeoJSON internally? |
Agree on Yep, property names can be quoted or unquoted (e.g. @matteblair you're following my thinking too -- I considered an array syntax, but you're correct JS YAML parser doesn't support it, and then it seemed just as complicated or more to parse it out manually from a string key. And this type of dot notation would be valid JS. Agree |
@nvkelso can you provide an example tile/location where that property shows up? Not finding it in a quick search. |
…ains some or all of a list of values
|
Can you elaborate on how you think we would want to filter on and use these array fields? For example, are the index positions 0, 1, etc. going to reliably reflect a fixed network "level" (national highway, state highway, etc.)? It seems like we couldn't necessarily guarantee that for all data? It's easy enough to match on the values, like "does
But that also doesn't fit simple filter matching syntax (it's more like the complex destructuring matching offered JS and other languages... which is cool but likely overkill here!); so we'd probably want a JS filter function for it as currently stored. Let's figure out how we want to style them, then determine what additional scene syntax and/or data format changes are needed (since they aren't in use anyway, right?). @matteblair other thoughts? |
Mostly I'm interested in multishield support, for roads, walking paths, bicycle, and transit. As long as this gets us part way there, and it's possible to step all the way there with an extension then I'm good. |
I don't know the full range of data for shields, but for the case above it we might be able to use an object property like: "networks": { "US:US": "101", "US:CA": "128" } Then do filtering and styling like: filter: { networks.US:US : true }
draw:
text:
text_source: networks.US:US This implies that property accessors work in styling expressions as well as filtering expressions - not sure if that was planned or not. |
😂 I think this is taking a complex turn when I'm just interested in multi-shields ;) |
It's the tangram way. I feel comfortable we can prototype multi-shields
with this data and some of the new syntax, and then go from there.
…On Tue, May 7, 2019 at 5:24 PM Nathaniel V. KELSO ***@***.***> wrote:
😂 I think this is taking a complex turn when I'm just interested in
multi-shields ;)
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#715 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAAECXMUZACAUKRZ7CUAPVDPUHXQZANCNFSM4HHMPEXA>
.
|
@nvkelso I don't think I understand what you mean when you say "multi-shields". Can you explain? |
The section of road given as an example above has data to support 2
shields, a US route and a California route. On many maps both routes would
have a shield drawn, so 2 shields total in this example. Often this is zoom
13+ as mid zooms can only accommodate 1 shield for density issues. But both
routes will be signed in real life, on the ground.
…On Tue, May 7, 2019 at 19:15 Matt Blair ***@***.***> wrote:
@nvkelso <https://github.com/nvkelso> I don't think I understand what you
mean when you say "multi-shields". Can you explain?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#715 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAGQIO4U55TSXTY5JEAXJBDPUIZSVANCNFSM4HHMPEXA>
.
|
Sometimes source data includes properties with a richer object format than just strings or numbers -- e.g. arrays, nested objects, etc. The MVT spec doesn't prescribe explicit behavior for these cases, but notes that common tools such as Tippecanoe and Mapnik will encode these properties as stringified JSON.
This requires client-side support for parsing these fields. This PR adds support for this on MVT data sources through a new
parse_json
property:parse_json
istrue
, then each property will be checked to see if it "looks like" stringified JSON (defined as a string with first character being{
or[
); if so, it is parsed as JSON (withJSON.parse
).parse_json
is an array of property names, only those specific properties are checked for JSON parsing. This is preferred to the above, because it limits the parsing impact to only the fields that need it.parse_json
is undefined/null/false, no special parsing of properties is done (e.g. the current behavior).Example usage:
These parsed properties will now be properly returned as full JS objects through functions such as
scene.getFeatureAt()
orscene.queryFeatures()
.To make use of these properties in filtering and styling, you will need to write a JS function to access the complex properties, e.g. if
prop_a
is an array of values, you could filter on it containing the valuex
like so:filter: function() { return feature.prop_a.indexOf('x') > -1; }