I have a collection of geoJSON LineString objects and need to determine which is closest to a point. I don't have much experience with Mongo DB, but have used the $geoNear to find closest points. Is there a way to adapt this to work with a collection of LineStrings?
Example collection:
{
"_id": ObjectId("5ee3e2deee404124a8ba4382"),
"geoJSON": {
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-85.5,
31.0
],
[
-85.6,
31.0
]
]
}
}
}
{
"_id": ObjectId("5ee3e2deee404124a8ba4383"),
"geoJSON": {
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-85.55,
31.5
],
[
-85.6,
31.5
]
]
}
}
}
{
"_id": ObjectId("5ee3e2deee404124a8ba4384"),
"geoJSON": {
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-85.5,
32.0
],
[
-85.6,
32.0
]
]
}
}
}
I'd like to search this collection to determine which line is closest to the point [-85.55, 31.77]. This should return the third line (blue line in the image below). Is there a way to do this efficiently in MongoDB?
Plot
Related
Using MongoDB stuck with the strange problem that polygon position on the map doesn't match the polygon points searched by $geowithin command.
This point shouldn't be in the polygon based on UI view -> however found by Mongo query.
-88.35311589225228, 50.46582815393761
Checked different version of MongoDB, drivers & etc -> however didn't help. Any ideas what can be the issue? Or just also difference?
DB Query:
db.device.find({
'location': {
$geoWithin: {
$geometry: {
type: 'Polygon',
coordinates: [[[-94.43847656250001, 52.855864177853995], [-87.89062500000001, 45.9511496866914], [-79.93652343750001, 46.55886030311719], [-94.43847656250001, 52.855864177853995]]] }
}
}
}
);
Visual representative:
https://geojson.io/#map=5.06/50.09/-88.52
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Point",
"coordinates": [
-88.35311589225228, 50.46582815393761
]
}
},
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-94.43847656250001,
52.855864177853995
],
[
-87.89062500000001,
45.9511496866914
],
[
-79.93652343750001,
46.55886030311719
],
[
-94.43847656250001,
52.855864177853995
]
]
]
}
}
]
}
I plot lines correctly on a Mapbox iOS map using a geojson files I have created.
I read the geojson file and associate it to a shape like so:
shapeFromGeoJSON = try? MGLShape(data: jsonData, encoding: String.Encoding.utf8.rawValue)
Then I create a linesSource and a linesLayer and then I show the linesLayer on the map correctly:
linesSource = MGLShapeSource(identifier: "polyline", shape: shapeFromGeoJSON, options: nil)
linesLayer = MGLLineStyleLayer(identifier: "polyline", source: linesSource)
mapView.style?.addSource(linesSource)
mapView.style?.addLayer(linesLayer)
Inside the geojson file, each line is represented by a "geometry" with multiple "coordinates" of type "LineString".
I need to do some special processing that involves knowing all the coordinates of the points making the lines.
Question: how can I get all the multiple point coordinates of each LineString from linesSource?
Here's my geojson file for testing:
{
"features":
{
"type": "Feature",
"properties": {},
"geometry": {
"coordinates": [
-9.316333,
38.680709
],
"type": "Point"
},
"id": "1234"
},
{
"type": "Feature",
"properties": {},
"geometry": {
"coordinates": [
[
-9.31687,
38.680772
],
[
-9.317531,
38.679794
],
[
-9.318001,
38.679196
],
[
-9.318436,
38.678612
],
[
-9.318592,
38.678354
]
],
"type": "LineString"
},
"id": "567"
},
{
"type": "Feature",
"properties": {},
"geometry": {
"coordinates": [
-9.316057,
38.680838
],
"type": "Point"
},
"id": "89"
},
{
"type": "Feature",
"properties": {},
"geometry": {
"coordinates": [
-9.316719,
38.680715
],
"type": "Point"
},
"id": "1011"
},
{
"type": "Feature",
"properties": {},
"geometry": {
"coordinates": [
-9.315931,
38.681066
],
"type": "Point"
},
"id": "1213"
}
],
"type": "FeatureCollection"
}
From my experiences with MapBox, not everything is easily user accessible. It might just be easiest to make a simple struct, decode the data into that, and access the coordinates from there.
I am creating a carpooling app that offers a list of trips (Departure City -> Arrival City).
I type the desired departure and arrival coordinates. And I get back the best options
My goal is to create a mongo request that return best routes that comes closest to my departure address and my arrival address
Example:
Departure Sèvres coordinates: [ 2.210590 , 48.824169 ]
Arrival Capbreton coordinates: [ -1.431370 , 43.640080 ]
I tried to combine this with $and operator but I'm not sure that is the solution... ("Too many geoNear expressions")
db.trip.find({
$and: [
{
"departureLocation": {
$near: {
$geometry: {
type: "Point",
coordinates: [ 2.210590 , 48.824169 ]
},
}
}
},
{
"arrivalLocation": {
$near: {
$geometry: {
type: "Point",
coordinates: [ -1.431370 , 43.640080 ]
},
}
}
}
]
}, {"departure": 1, "arrival": 1})
Here my trips
[
{
"_id": "5d24d2e4ea5e2a29ea0f0e77",
"departure": "Paris",
"arrival": "Givrand",
"departureLocation": {
"type": "Point",
"coordinates": [
2.352222,
48.856613
]
},
"arrivalLocation": {
"type": "Point",
"coordinates": [
-1.88465,
46.67119
]
},
},
{
"_id": "5d3c594e6562967b8ad9e62b",
"departure": "Bordeaux",
"arrival": "Biarritz",
"departureLocation": {
"type": "Point",
"coordinates": [
-0.57918,
44.837788
]
},
"arrivalLocation": {
"type": "Point",
"coordinates": [
-1.558626,
43.48315
]
},
},
{
"_id": "5d3c59e96562967b8ad9e62c",
"departureLocation": {
"type": "Point",
"coordinates": [
2.18919,
48.810032
]
},
"departure": "Chaville",
"arrival": "Seignosse",
"arrivalLocation": {
"type": "Point",
"coordinates": [
-1.37524,
43.69011
]
},
},
{
"_id": "5d3c5a8a6562967b8ad9e62d",
"departureLocation": {
"type": "Point",
"coordinates": [
-1.553621,
47.218372
]
},
"departure": "Nantes",
"arrival": "Hossegor",
"arrivalLocation": {
"type": "Point",
"coordinates": [
-1.3952,
43.663342
]
},
}
]
Expected result :
(Chaville - Seignosse) should be placed at the first position of the result because it's the best option if I'm looking for a ride (Sèvres - Capbreton)
Unfortunately for you, there's no mongodb-only solution to resolve this as:
Only one $geonear expression can be used in a find() method.
Only the first stage of an aggregation can be a $geonear stage.
$geonear can not be used inside a $facet stage.
You have to deal with this programmatically, to run 2 separate geonear queries on your collection and find the best of the both resultsets. Before doing this, think about what is 'the best' result (closest to departure, arrival, lowest mean of both, etc...)
I'm trying to create an Elasticsearch mapping for Twitter's Place geo bounding_box array and I can't get Elasticsearch to index it as a geo bounding box. In my app, I will be getting the raw JSON from Twitter4j, however the bounding box does not close the bounding box, so for the purpose of this test, I edited the json and closed it. I'm using Elastic cloud (ES v5) and the Rest API and then visualizing with Kibana.
Here is the mapping I'm trying to use. I've tried several variations with and without a "properties" block and it doesn't work. With this mapping, I am successfully able to PUT the mapping, but when I POST the document, Kibana recognizes the array as an unknown field type.
The Point coordinates field is indexed as a geopoint just fine, it's the bounding box that does not.
Here is my mapping:
PUT /testgeo
{
"mappings": {
"tweet": {
"_all": {
"enabled": false
},
"properties": {
"created_at": {
"type": "date",
"format": "EEE MMM dd HH:mm:ss Z YYYY||strict_date_optional_time||epoch_millis"
},
"coordinates": {
"properties": {
"coordinates": {
"type": "geo_point",
"ignore_malformed": true
}
}
},
"place": {
"properties": {
"bounding_box": {
"type": "geo_shape",
"tree": "quadtree",
"precision": "1m"
}
}
}
}
}
}
}
Here is the snippet of the document I am trying to POST (NOTE: I manually added the 5th array element to close the bounding box).
POST /testgeo/tweet/1
{
...
"coordinates": {
"type": "point",
"coordinates": [
0.78055556,
51.97222222
]
},
"place": {
"id": "0c31a1a5b970086e",
"url": "https:\/\/api.twitter.com\/1.1\/geo\/id\/0c31a1a5b970086e.json",
"place_type": "city",
"name": "Bures",
"full_name": "Bures, England",
"country_code": "GB",
"country": "United Kingdom",
"bounding_box": {
"type": "polygon",
"coordinates": [
[
[
0.773779,
51.96971
],
[
0.773779,
51.976437
],
[
0.781794,
51.976437
],
[
0.781794,
51.96971
],
[
0.773779,
51.96971
]
]
]
},
"attributes": {
}
},
If anyone can identify the reason for this and correct it, I would be most appreciative.
NOTE 1:: I tried using the mapping and document examples from Elastic's geo_shape documentation page and Kibana again showed the location field as unknown type.
PUT /testgeo
{
"mappings": {
"tweet": {
"_all": {
"enabled": false
},
"properties": {
"location": {
"type": "geo_shape",
"tree": "quadtree",
"precision": "1m"
}
}
}
}
}
POST /testgeo/tweet/1
{
"location" : {
"type" : "polygon",
"coordinates" : [
[ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0] ]
]
}
}
Turns out that Kibana simply does reflect the type for GeoShape's. When doing a geo query, however, Elasticsearch returns correct results.
For example:
"query": {
"bool": {
"must": {
"match_all": {}
},
"filter": {
"geo_shape": {
"place.bounding_box": {
"shape": {
"type": "polygon",
"coordinates": [
[
[
0.773779,
51.96971
],
[
0.773779,
51.976437
],
[
0.781794,
51.976437
],
[
0.781794,
51.96971
],
[
0.773779,
51.96971
]
]
]
},
"relation": "within"
}
}
}
}
}
}
Even though you seem to have found a solution to your problem I just wanted to say there is a fix now for this issue by using the coerce option in the mapping for geo_shape like so:
"properties": {
"bounding_box": {
"type": "geo_shape",
"tree": "quadtree",
"precision": "1m",
"coerce": true
}
}
Also see:
https://github.com/elastic/elasticsearch/pull/11161
I'm using mongo to store some geolocalized data, with the goal of retriving them using $geointersect. Specifically I have this document stored in my db:
{
"loc": {
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-179.875,
-89.875
],
[
179.875,
-89.875
],
[
179.875,
89.875
],
[
-179.875,
89.875
],
[
-179.875,
-89.875
]
]
]
},
"crs": {
"type": "name",
"properties": {
"name": "urn:x-mongodb:crs:strictwinding:EPSG:4326"
}
},
"type": "Feature",
"properties": {}
},
"_id": "576af8e31d41c87fa1f1d04f"
}
Which as you may notice covers almost the entire World. Now it doesn't matter what coordinates I input for my $geointersect query, it will never be returned... Does anyone know why?
An example of the query I'm using could be:
[
{
"loc.geometry": {
"$geoIntersects": {
"$geometry": {
"type": "Polygon",
"coordinates": [
[
[
13.4307861328125,
41.599013054830216
],
[
13.9801025390625,
41.599013054830216
],
[
13.9801025390625,
41.80407814427234
],
[
13.4307861328125,
41.80407814427234
],
[
13.4307861328125,
41.599013054830216
]
]
]
}
}
}
},
{
"loc": 1
}
]
Of course the coordinates of the query are contained inside the polygon in the saved document (I mean... it's as big as the the world, duh!) but for some reason it doesn't find any match... I'm kinda lost.
Just looking into this now. If the polygon is solid and bigger than an earth's hemisphere, mongo returns everything outside of the area. check out their big poly and crs in the geoWithin documentation