MongoDB: adding a field from another collection with geoNear - mongodb

I have two collections, which both have Geospatial Indexes:
people
[
{
"name": "Steve",
...
"geometry": {"type": "Point", "coordinates": [90, 90]}
},
{
"name": "John",
...
"geometry": {"type": "Point", "coordinates": [-90, -90]}
}
]
zones
[
{
"zone": "Place_0001001",
"geometry":
{
"type": "Polygon",
"coordinates": [
[90.0001, 90.0001],
[90.0002,90.0000],
...
]
},
"avg_income": 9999,
"avg_age": 50
]
For analysis purposes I need the Zone information on a Person level, which requires to lookup the nearest Zone to each Person and then retrieve the fields.
I haven't been able to assign the nearest Zone to a Person, I understand the basis of the code should be something like this, a geoNear with a limit of 1:
db.people.aggregate([
{
$geoNear: {
near: { type: "Point", coordinates: [90,90]},
spherical: true,
distanceField: "distance"
},
},
{
$limit: 1,
},
]);
But I'm unsure on how to both reference the Zone and add it to the People collection.

Related

MongoDB - strange inconsistency in geowithin polygon search

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
]
]
]
}
}
]
}

MongoDB - Insert field names as string instead of getting the value

I want to create a new location field from already existing longitude and latitude.
db.neigborhood.updateMany({}, {
$set: {
"location": {
"type": "Point",
"coordinates": ["$longitude", "$latitude"]
}
}});
I wrote this code that should create the new field, but the problem is that instead of the field values I get the names as strings.
{
"_id": {
"$oid": "626a01f1df85b4b2937ece2d"
},
"latitude": "10.4980067",
"longitude": "-66.8335096",
"location": {
"type": "Point",
"coordinates": [
"$longitude",
"$latitude"
]
}
}
What am I doing wrong that I get "$longitude" instead of the -66.8335096 value?
Works with Update with Aggregation Pipeline.
db.neigborhood.updateMany({},
[
{
$set: {
"location": {
"type": "Point",
"coordinates": [
"$longitude",
"$latitude"
]
}
}
}
])
Sample Mongo Playground

MongoDB $geoNear Aggregation on another collection

I have a database with two collections like so:
[
{
"name": "Person A",
"location": {"type": "Point", "coordinates": [180, 90]}
},
{
"name": "Person B",
"location": {"type": "Point", "coordinates": [-180, -90]}
}
]
[
{
"name": "Store A",
"location": {"type": "Point", "coordinates": [180, 90]}
},
{
"name": "Store B",
"location": {"type": "Point", "coordinates": [-180, -90]}
}
]
For each person, I want to find the nearest place. I could get it to find the nearest place for one specific pair of coordinates, not for the entire collection. Is there any way to do that without using foreach?
This is the closest I got following the MongoDB documentation:
// Current $geoNear:
{
// Instead of having to give constants of a single
// point, I want to compare against all coordinates
// of another collection. ↓
near: {"type":"Point","coordinates":[-180, 90]},
distanceField: 'distance',
maxDistance: 50,
spherical: true
}
This can be achieved using aggregation.
[{
$lookup: {
from: "places",
let: {
"personPoint": "$location"
},
as: "nearestPlace",
pipeline: [
{
$geoNear: {
near: "$$personPoint",
spherical: true,
distanceField: "distance",
maxDistance: 50,
}
},
{
$unwind: "$location"
},
]
}
},
{
$unwind: {
path: "$nearestPlace",
preserveNullAndEmptyArrays: true
}
}]
I couldn't test it on playground because of geo index. So might require some minor fix. If anyone can make it work on playground heres the link
https://mongoplayground.net/p/aROX976gYzC

Can I Use MongoDB Geospatial Query to Find Closest LineString to Point?

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

Mongo request with GeoJson Objects and multiple $near on different fields

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...)