Mongodb aggregate on two collections based on geopoint - mongodb

I have two collections
person
{
"name": "Mike",
"age": 42,
"address": {
"location": {"type": "Point", "coordinates": [12.3456, 78.9101]}
}
}
restaurant
{
"name": "Bistro",
"type": ["Maxican", "Italian"],
"location": {"type": "Point", "coordinates": [12.3555, 78.9333]}
}
I've created spherical indexes on both collections
db.person.createIndex({"address.location": "2dsphere"})
db.restaurant.createIndex({"location": "2dsphere"})
Now I want to find all the restaurants near to a person using lat/long in both collections.
for e.g find all the restaurants within 10KM of a person. result will look like below
{
"name": "Mike",
"age": 42,
"address": {
"location": {"type": "Point", "coordinates": [12.3456, 78.9101]}
},
"nearby_restaurants": [{"name": "Bistro", "distance": 5.3}] // this means bistro is 5.3 KM away from this person
}
Notice that, I'm only using name field from restaurant collection and an additional field distance which will be calculated after the query.
I want to do this for all person. so basically for each person, i have to scan the whole restaurant collection every time.
To achieve this I thought of using lookup with aggregate, something like below
db.person.aggregate([
{
$lookup: {
from: "restaurant",
let: {"personPoint": "$address.location"},
as: "nearby_restaurants",
pipeline: [
{
$geoNear: {
near: "$$personPoint",
spherical: true,
distanceField: "distance",
maxDistance: 10 * 1000, // within 10 KM
distanceMultiplier: 0.001 // get the result in KM
}
},
{
$unwind: "$location"
},
]
}
},
{
$unwind: {
path: "$nearby_restaurants",
preserveNullAndEmptyArrays: true
}
}
])
This doesnt work at all. I get this error: $geoNear requires a 'near' option as an Array"
I tried to look at different sources but couldnt understand and fix the error.
PS: If currently, it's not possible through lookups/aggregate, how can we achieve the same through looping over each person's document?

Related

$geoWithin query fail to retrieve point included in the queried polygon - v2

I've already ask the same question in this post. My example was subject to earth curvature issue so lets have a look to another one.
This time I have two nested polygons. A large one and a smaller one. Performing a $geoWithin query with the larger one return no document while the document is found using the smaller polygon. Any thoughts?
https://mongoplayground.net/p/V_3-s-itngA
The document I'm trying to query which is located on an island on France west coast.
{
"_id": {
"$oid": "625fec0f6476793a4581d172"
},
"featureOfInterest": {
"samplingFeature": {
"geometry": {
"type": "Point",
"coordinates": [
-2.3433781679840138,
46.713764788942484
]
},
"name": [
{
"lang": "en",
"text": "France"
}
],
"type": "Feature"
}
}
}
And the query
db.collection.aggregate([
{
$match: {
"$or": [
//Largest polygon - return no document
{
"samplingFeature.geometry": {
"$geoWithin": {
"$geometry": {
"type": "Polygon",
"coordinates": [
[[-55.722656,34.161818],[58.007813,34.161818],[ 58.007813,53.540307],[ -55.722656, 53.540307], [-55.722656,34.161818]]]
}
}
}
},
//Smallest polygon - return the document
//{
// "samplingFeature.geometry": {
// "$geoWithin": {
// "$geometry": {
// "type": "Polygon",
// "coordinates": [[[-5.800781, 42.682435], [9.316406, 42.682435], [9.316406, 50.625073], [-5.800781, 50.625073], [-5.800781, 42.682435]]]
// }
// }
//}
//}
]
}
}
])
You've bent the planet other way round. The coordinates in your post make these boxes:
the marker is clearly outside the the larger box.
Please use the link to jsfddle in my answer to your previous question instead of globes, or wherever you get your image from. The shortest path between 2 points far away does not necessarily follow longitudes and latitudes. Please read about the math of Geodesic calculations used in mongo geospatial queries.

$geoWithin query fail to retrieve point included in the queried polygon

I'm trying to query a document using its location with two polygons that are quite similar. Both includes the location of the document but one finds it and the other not. I thought that this was related to "big polygons" but I managed to reduce the polygons enough to rule out this possibility. See previous post. Any idea explaining such a difference?
Playground: https://mongoplayground.net/p/sTEtYD3HU8m:
Document:
{
"_id": {
"$oid": "63ef9379e671073bfb963145"
},
"geometry": {
"type": "Point",
"coordinates": [
2.834,
47.264
]
},
"_class": "org.example.springdatamongodbgeowithinissue.model.SamplingGeometry"
}
Is not in search results for this polygon:
{
"geometry": {
"$geoWithin": {
"$geometry": {
"type": "Polygon",
"coordinates": [
[
[
-16.1,
49.12
],
[
-16.1,
46.156
],
[
16.1,
46.156
],
[
16.1,
49.12
],
[
-16.1,
49.12
]
]
]
}
}
}
}
Still the same issue with Earth's curvature. Your area is long enough to take it into account:
zooming in and's clearly outside:
The map: https://jsfiddle.net/blex18/w9g4bzyk/1/
var map = new google.maps.Map(document.body, {zoom:5,center:{lat:47.264,lng:2.834}});
new google.maps.Polygon({geodesic:true,map:map,geodesic:true,
path:[
{lat:49.12,lng:-16.1},
{lat:46.156,lng:-16.1},
{lat:46.156,lng:16.1},
{lat:49.12,lng:16.1},
{lat:49.12,lng:-16.1}]});
new google.maps.Marker({
position: {lat:47.264,lng:2.834},
map,
title: "Here",
});

MongoDB: GeoJSON object type index, Can't extract geo keys

I have made many the below GeoJSON Point objects in MongoDB Compass as per the docs
{
"_id": {
"$oid": "5e86d275a3d7fd05e4f022a8"
},
"location": {
"type": "point",
"coordinates": ["-110.85458435", "39.68476146"]
},
"website": "carbonmedicalservice.com",
"address": "125 S Main St",
"state": "UT",
"zip": "84526",
"name": "Carbon Medical"
}
I want to be able te search the collection to return all records within an reactangle, I believe I need to add a Geospatial Indexe to the location but I get the error shown below...
This is how I entered the data:
In a GeoJSON type, coordinates should be float/double not string.
Also, the type should be Point, not point in your case. So, the GeoJSON in your case should be:
{
"type": "Point",
"coordinates": [-110.85458435, 39.68476146]
}
instead of
{
"type": "point",
"coordinates": ["-110.85458435", "39.68476146"]
}

MongoDb query - aggregation, group, filter, max

I am trying to figure out specific mongoDb query, so far unsuccessfully.
Documents in my collections looks someting like this (contain more attributes, which are irrelevant for this query):
[{
"_id": ObjectId("596e01b6f4f7cf137cb3d096"),
"code": "A",
"name": "name1",
"sys": {
"cts": ISODate("2017-07-18T12:40:22.772Z"),
}
},
{
"_id": ObjectId("596e01b6f4f7cf137cb3d097"),
"code": "A",
"name": "name2",
"sys": {
"cts": ISODate("2017-07-19T12:40:22.772Z"),
}
},
{
"_id": ObjectId("596e01b6f4f7cf137cb3d098"),
"code": "B",
"name": "name3",
"sys": {
"cts": ISODate("2017-07-16T12:40:22.772Z"),
}
},
{
"_id": ObjectId("596e01b6f4f7cf137cb3d099"),
"code": "B",
"name": "name3",
"sys": {
"cts": ISODate("2017-07-10T12:40:22.772Z"),
}
}]
What I need is to get current versions of documents, filtered by code or name, or both. Current version means that from two(or more) documents with same code, I want pick the one which has latest sys.cts date value.
So, result of this query executed with filter name="name3" would be the 3rd document from previous list. Result of query without any filter would be 2nd and 3rd document.
I have an idea how to construct this query with changed data model but I was hoping someone could lead me right way without doing so.
Thank you

Find specific mongoldb document from nested array

This is my document in MongoDB:
{
"_id": {
"$oid": "566193b0c9b5290f234242"
},
"name": "fake-name-1",
"profiles": [
{
"real-name": "fake-name-1",
"color": "fake-color-1"
},
{
"real-name": "fake-name-2",
"color": "fake-color-2",
"active": true
},
{
"real-name": "fake-name-3",
"color": "fake-color-3"
}
]
}
I'm real newbie to MondoDb, and are trying to find the document where profiles contains a real-name with "MArtin43221" and active = true.
How do I create a search query for this?
I've tried:
{"profiles": ["real-name":"MArtin43221", "active":true]}
Try elemMatch:
db.collection.find({"profiles": {$elemMatch:{"real-name":"MArtin43221", "active":true}}})