Map{box,libre} expression syntax for dynamic property value - mapbox

I am stuck trying to write an expression that evaluates to a number for my paint.circle-radius property.
If I set something like this, to use the radius feature property, it works fine:
"circle-radius": {
property: "radius",
type: "exponential",
stops: [
[{ zoom: 9, value: 1 }, 10],
[{ zoom: 9, value: 10 }, 80]
]
},
Trying to use an expression to calculate the value does not work:
"circle-radius": [
"literal",
{
property: ["case", ["has", "other"], "other", "radius"],
type: "exponential",
stops: [
[{ zoom: 9, value: 1 }, 10],
[{ zoom: 9, value: 10 }, 80]
]
}
]
The full example is here: https://codesandbox.io/s/laughing-mclean-zftnpr?file=/index.html
I would expect a yellow circle on the top with a radius of 10. Instead, the layer does not render, and all you see are the tomato circles.
Error in console:
circle-radius: Expected number but found object instead

You are using property syntax that was deprecated years ago, and attempting to combine it with current expression syntax in a way that won't work.
You want something like this:
"circle-radius":
["interpolate",
["case", ["has", "other"], ["get", "other"], ["get", "radius"]],
1, 10,
10, 80
]

Related

MongoDB can't parse query (2dsphere): Java API

I have the following object in my Collection:
{
"_id":"test123",
"footprint":{
"type":"Polygon",
"coordinates":[
[
[10, 30], [20, 45], [38, 38], [43, 38], [45, 30], [10, 30]
]
]
}
}
with index of type "2dsphere" on "footprint" attribute.
Now, I would like to implements the geospatial query "overlaps", as implemented by ST_Overlaps in PostGIS: https://postgis.net/docs/ST_Overlaps.html.
Due to the fact that MongoDB doesn't support "overlap" natively (only within, intersect and near) and according to the above definition, I whould return all overlapping documents not totally within the search area.
Using mongo-java-drivers 3.12.8, I developed the following Bson filter:
Polygon polygon = new Polygon(
new PolygonCoordinates(
Arrays.asList(
new Position(41.62109375000001d, 38.087716380862716d),
new Position(41.870727539062514d, 37.998201197578084d),
new Position(41.72393798828124d, 38.01268326428104d),
new Position(41.62109375000001d, 38.087716380862716d)
)
)
);
Bson spatialFilter = Filters.and(
Filters.geoIntersects("footprint", polygon),
Filters.not(Filters.geoWithin("footprint", polygon))
);
But when I execute the following:
db.collection.find(spatialFilter);
I get the following error:
Query failed with error code 2 and error message 'can't parse extra field: $geoWithin: { $geometry: { type: "Polygon", coordinates: [ [ [ 41.62109375000001, 38.08771638086272 ], [ 41.87072753906251, 37.99820119757808 ], [ 41.72393798828124, 38.01268326428104 ], [ 41.62109375000001, 38.08771638086272 ] ] ] } }' on server localhost:27017
As explained here MongoDB can't parse query (2dsphere): two conditions, it seems that the "$and" wrapper filter is not correctly generated.
Am I wrong? Is there any workaround?
Thanks
Maybe, it was a bug in 3.12.8 version.
It seems fixed in 4.2.3 version

How to dynamically filter datasets based on their location

I'm trying to achieve the following behaviour with a mongodb query:
I have documents which have a field location and a 2dshere geospatial index on that field
The documents also have a field maxdistance
The location of the user is available in the variable user.gps as a GeoJSON point
The query currently looks like this:
query["location"] = {
$nearSphere: {
$geometry: user.gps,
$maxDistance: filterDistance
}
};
This query successfully selects all the datasets in a given filterDistance relative to the user.
What i'd like to have now is "If document.maxdistance field > 0 and the distance to the user is greater than document.maxdistance" do not select the dataset.
So i have documents that should not be found if the user lives in a distance greater than a given distance saved inside the document.
I don't know hot to express this in a mongodb query and i couldn't find any example of such a query.
$near/$nearSphere don't support per-document distance. Only per query. The main reason is sorting by distance. If you need only filtering you can use $geoIntersects/$geoWithin, but you will need to change documents to contain a polygon of the covered area, like a circle Pi*2*distance around it's location.
Example:
Assuming you have a document:
{
loc: { type: "Point", coordinates: [ 10, 20 ] },
distance: 10
}
So that it is returned when user's coordinate is within the radius, e.g. [12, 25], and is not returned when user's coordinate is outside, e.g. [12,30].
For that documents should be updated to convert loc/distance pair to a polygon. For the sake of simplicity I'll use octagon, but you may want to increase number of vertices for more accurate results:
{
loc: { type: "Point", coordinates: [ 10, 20 ] },
distance: 10,
area: {
type : "Polygon",
coordinates : [[
[ 17, 27 ],
[ 10, 30 ],
[ 3, 27 ],
[ 0, 20 ],
[ 3, 13 ],
[ 10, 10 ],
[ 17, 13 ],
[ 20, 20 ],
[ 17, 27 ]
]]
}
}
Then you can use $geoIntersects to find documents which area includes user's coordinates:
db.collection.find({
area: {
$geoIntersects: {
$geometry: { type: "Point" , coordinates: [ 12, 25] }
}
}
})

$centerSphere is not returning any geojson polygons (mongoDB)

I am having a lot of trouble with the following Mongo query
location: { $geoWithin: { $centerSphere: [[lon,lat],radians] } }
It only returns geoJSON Points and ignores all my geoJSON Polygons for some reason. The documentation states:
You can use the $centerSphere operator on both GeoJSON objects and legacy coordinate pairs.
I am using Mongoose to run the queries and my geoJSON is coverted from WellKnown Text by the NPM module wellknown. This is how my geoJSON looks after the wellknown module has converted them:
"location": {
"coordinates": [
22.1,
33.3
],
"type": "Point"
}
and
"location": {
"coordinates": [
[
[
43,
30
],
[
40,
28
],
[
49,
27
],
[
43,
30
]
],
[
[
44,
28
],
[
44.7,
28.8
],
[
46,
28
],
[
44,
28
]
]
],
"type": "Polygon"
}
My Mongoose schema is defined as:
location: {
type: schema.Types.Mixed,
index: '2dsphere',
required: false
}
I should add that the withinPolygon methods work as expected and I get both the Points and Polygons returned. The following works completely fine:
location: { $geoWithin: { $geometry: geoJSON } }
Thank you for any help. I have read the documentation and can't see anywhere where it mentions that the $centerSphere only returns geoJSON Points.
With the recent release of MongoDB version 3.6.0-rc0, you can now query GeoJSON LineStrings and Polygons with $geoWithin geospatial operator $centerSphere.
See also SERVER-27968 more information about the update.

RethinkDB - How to group on aggregated time intervals

I'd like to group and average on dynamic time intervals. Similar question to: Grouping into interval of 5 minutes within a time range.
Right now, I am using the query:
r.db('windMachine').table('stats3')
.between(r.time(2015, 5, 7, 18, 0, 0, "Z"), r.time(2015, 5, 7, 24, 0, 0, "Z"), {index: "date"})
.group([r.row("date").hours(), r.row("date").minutes()])
.avg("TMP0")
Which returns:
[
{
"group": [
21,
2
],
"reduction": 22.802153846153846
},
{
"group": [
21,
3
],
"reduction": 22.6628
},
{
"group": [
21,
4
],
"reduction": 22.384324324324318
}
]
I'd like to group this further, down into 5 minute (or other) intervals. What is the best way to go about doing this?
I actually met a similar problem and here is what I did:
.group(r.row('date').toEpochTime().sub(r.row('date').toEpochTime().mod(<INTERVAL_IN_SECONDS>))
What this do is to group time by <INTERVAL_IN_SECONDS>
I don't know if this is the best way for the task but it works for me.

MongoDB $elemMatch of $elemMatch and good practice

H,
I'm trying to update the version field in this object but I'm not able to make a query with 2 nested $match. So what I would like to do is get the record with file id 12 and version 1.
I would ask also if is it a good practice have more the one nested array in mongoDB (like this object)...
Query:
db.collection.find({"my_uuid":"434343"},{"item":{$elemMatch:{"file_id":12,"changes":{$elemMatch:{"version":1}}}}}).pretty()
Object:
{
"my_uuid": "434343",
"item": [
{
"file_id": 12,
"no_of_versions" : 1,
"changes": [
{
"version": 1,
"commentIds": [
4,
5,
7
]
},
{
"version": 2,
"commentIds": [
10,
11,
15
]
}
]
},
{
"file_id": 234,
"unseen_comments": 3,
"no_of_versions" : 2,
"changes": [
{
"version": 1,
"commentIds": [
100,
110,
150
]
}
]
}
]
}
Thank you
If you want the entire documents that satisfy the criteria returned in the result, then I think it's fine. But if you want to limit the array contents of item and changes to just the matching elements, then it could be a problem. That's because, you'll have to use the $ positional operator in the projection to limit the contents of the array and only one such operator can appear in the projection. So, you'll not be able to limit the contents of multiple arrays within the document.