How do I reverse the coordinates with mongodb? - mongodb

I have these coordinates in the wrong order I need to reverse them for all collections:
{
_id: ObjectId("638f9866d9014fabfc47275e"),
address: '801 Pine St, Anchorage, AK',
name: 'Russian Jack Skatepark',
location: { type: 'Point', coordinates: [ 61.214855, -149.793563 ] }
}

You can use $reverseArray as follow:
db.collection.updateMany({},
[
{
$set: {
"location.coordinates": {
$reverseArray: "$location.coordinates"
}
}
}
])
Playgrouund

Related

How do I convert all geo locations in mongo db from strings to floats?

skatespot-dev> db.parks.findOne();
{
_id: ObjectId("638f9866d9014fabfc47275e"),
address: '801 Pine St, Anchorage, AK',
name: 'Russian Jack Skatepark',
location: { type: 'Point', coordinates: [ '61.214855', '-149.793563' ] }
}
I need to run a query to convert all coodinates to floats i guess.
You can convert them to double using update with pipeline, like this:
db.collection.updateMany({},
[
{
$set: {
"location.coordinates": [
{
$toDouble: {
$first: "$location.coordinates"
}
},
{
$toDouble: {
$last: "$location.coordinates"
}
}
]
}
}
])
See how it works on the playground example

Get only matched array object along with parent fields

I also checked the following question and tried various other things but
couldn't get it working
Retrieve only the queried element in an object array in MongoDB collection
I have the following document sample
{
_id: ObjectId("634b08f7eb5cb6af473e3ab2"),
name: 'India',
iso_code: 'IN',
states: [
{
name: 'Karnataka',
cities: [
{
name: 'Hubli Tabibland',
pincode: 580020,
location: { type: 'point', coordinates: [Array] }
},
{
name: 'Hubli Vinobanagar',
pincode: 580020,
location: { type: 'point', coordinates: [Array] }
},
{
name: 'Hubli Bengeri',
pincode: 580023,
location: { type: 'point', coordinates: [Array] }
},
{
name: 'Kusugal',
pincode: 580023,
location: { type: 'point', coordinates: [Array] }
}
]
}
]
}
I need only the following
{
_id: ObjectId("634b08f7eb5cb6af473e3ab2"),
name: 'India',
iso_code: 'IN',
states: [
{
name: 'Karnataka',
cities: [
{
name: 'Kusugal',
pincode: 580023,
location: { type: 'point', coordinates: [Array] }
}
]
}
]
}
Following is the query that I have tried so far but it returns all the cities
db.countries.find(
{
'states.cities': {
$elemMatch: {
'name' : 'Kusugal'
}
}
},
{
'_id': 1,
'name': 1,
'states.name': 1,
'states.cities.$' : 1
}
);
I was able to achieve it with the help of aggregation.
db.countries.aggregate([
{ $match: { "states.cities.name": /Kusugal/ } },
{ $unwind: "$states" },
{ $unwind: "$states.cities" },
{ $match: { "states.cities.name": /Kusugal/ } }
]);
1st line $match will query the records with cities with only Kusugal
2nd & 3rd line $unwind will create a separate specific collection of documents from the filtered records
3rd line $match will filter these records again based on the condition
In simple aggregation processes commands and sends to next command and returns as an single result.

How to make and requests in mongodb queries

I've worked on this for about an hour now and I can't figure anything out that works so sorry if this is obvious.
I want my query to only return results where every result matches, but right now it returns a result if at least one match is found.
My document looks like this...
{
country: 'Great Britain',
data: [
{
school: 'King Alberts',
staff: [
{
name: 'John',
age: 37,
position: 'Head Teacher'
},
{
name: 'Grace',
age: 63,
position: 'Retired'
},
{
name: 'Bob',
age: 25,
position: 'Receptionist'
}
]
},
{
school: 'St Johns',
staff: [
{
name: 'Alex',
age: 22,
position: 'Head of Drama'
},
{
name: 'Grace',
age: 51,
position: 'English Teacher'
},
{
name: 'Jack',
age: 33,
position: 'Receptionist'
}
]
},
// ... more schools
]
}
The query I'm currently making looks like...
{ 'data.staff.name': { $in: names } }
and the 'names' array that is being provided looks like ['Bob', 'Grace', 'John', 'Will', 'Tom']. Currently both schools are being returned when I make this query, I think it's because the 'names' array contains 'Grace' which is a name present at both schools and so the document it matching. Does anyone know if there's a query I could make so mongodb only returns the school object if every name in the 'names' array is a member of staff at the school?
You need to use the aggregation pipeline for this, after matching the document we'll just filter out the none matching arrays, like so:
db.collection.aggregate([
{
$match: {
"data.staff.name": {
$in: names
}
}
},
{
$addFields: {
data: {
$filter: {
input: "$data",
cond: {
$eq: [
{
$size: {
"$setIntersection": [
"$$this.staff.name",
names
]
}
},
{
$size: "$$this.staff"
}
]
}
}
}
}
}
])
Mongo Playground

lookup with pipeline and geoIntersects that use let variable

I am trying to lookup for neighborhoods which match my condition - the boundries polygon intersects with the post's coordinates but I am unable to do it - cant use the let in my pipeline $match
example of post entity:
{
_id: ObjectId,
...,
location: {
...,
coordinates: {
type: 'Point',
coordinates: [number, number]
}
}
};
example of neighborhood entity:
{
_id: ObjectId,
...,
boundries: {
type: 'Polygon',
coordinates: [ [ [number, number], [number, number], [number, number], [number, number], [number, number] ] ]
}
};
example of query I am trying to "fix":
db.posts.aggregate([
{ $match: { _id: ObjectId('5a562e62100338001218dffa') } },
{
$lookup: {
from: 'neighborhoods',
let: { postCoordinates: '$location.coordinates.coordinates' },
pipeline: [
{
$match: {
boundries: {
$geoIntersects: {
$geometry: {
type: 'Point',
coordinates: '$$postCoordinates'
}
}
}
}
}
],
as: 'neighborhoods'
}
}
]);
Unfortunately coordinates can't be populated from document field.
Geospatial are query expressions and $let variables are only permitted to use in $match with $expr variant for aggregation expressions in $lookup pipeline.
You have to perform the query in two steps.
First step to get the coordinates for matching record.
var result = db.posts.findOne({ _id: ObjectId('5a562e62100338001218dffa')},{ _id: 0, 'location':1});
Second step to look for point in the polygon.
db.neighborhoods.find(
{
"boundries": {
$geoIntersects: {
$geometry: {
type: "Point" ,
coordinates: result.location.coordinates.coordinates
}
}
}
}
)

MongoDb find by value in array

here is the model of my collection :
classes:[{
class:String,
info:{
subjects:[String],
students:[{
name:String,
surname:String,
matriculae:Number,
path_1:String,
path_2:String
}],
classTeacher:{
name:String,
surname:String
}
}
}],
accademicYear:String}];
I'd like to retrive value 'matriculae' given the name,surname and accademicYear of a student. I cant wrap my head 'round it tho! Thanks for help.
If you mean you want the result flat format, try this:
School.aggregate([
{
$unwind: '$classes'
}, {
$project: {
accademicYear: 1,
students: "$classes.info.students"
}
}, {
$unwind: "$students"
}, {
$project: {
accademicYear: 1,
matriculae: "$students.matriculae",
name: "$students.name",
surname: "$students.surname",
}
}
])
In case of the classes is collection and accademicYear is inside of the classes collection.Plus added the match criteria.
db.getCollection('classes').aggregate([{
$project: {
accademicYear: 1,
students: "$info.students"
}
}, {
$unwind: "$students"
}, {
$project: {
accademicYear: 1,
matriculae: "$students.matriculae",
name: "$students.name",
surname: "$students.surname",
}
}, {
$match: {
name: name,
surname: surname,
accademicYear: year
}
}])