How to search nearest place in array object in mongodb - mongodb

the mongodb document 'contents' is
{
"_id" : ObjectId("57bd1ff410ea3c38386b9194"),
"name" : "4Fingers",
"locations" : [
{
"id" : "locations1",
"address" : "68 Orchard Rd, #B1-07 Plaza Singapura, Plaza Singapura, Singapura 238839",
"phone" : "+65 6338 0631",
"openhours" : "Sunday-Thursday: 11am - 10pm \nFriday/Saturday/Eve of PH*: 11am - 11pm",
"loc" : [
"1.300626",
"103.845061"
]
}
],
"comments" : [ ],
"modified" : 1472271793525,
"created" : 1472012276724,
"createdby" : "Admin",
"modifiedby" : "Admin",
"createdipaddress" : "localhost",
"modifiedipaddress" : null,
"types" : "Restaurant",
"category" : "FoodAndBeverages",
"logo" : "logo4Fingers.png",
"tags" : "western, chicken, restaurant, food, beverages"
}
I want to find the nearest place to my location that i get from HTML5 navigation. How do i query it? Data should be sorted in near to far order.
Thank you.

To query mongodb geospatial data first you need a geo spatial index on your location field.
Your location field is a string, it needs to be a numeric type, you need to update your data accordingly.
Create your index on numerical location data:
db.collection.createIndex( { "locations.loc" : "2d" });
Query:
var projection = {"locations.loc":1};
var query = {"locations.loc": {"$near":[1.300626, 103.845061], "$maxDistance": 0.5}};
db.collection.find(query, projection).pretty();
//result:
{
"_id" : ObjectId("57bd1ff410ea3c38386b9194"),
"locations" : [
{
"loc" : [
1.300626,
103.845061
]
}
]
}
var query2 = {"locations.loc": {"$near":[2.300626, 103.845061], "$maxDistance": 0.5}};
db.collection.find(query2, projection).pretty();
//result:
{}
The query result will be sorted always, with nearest as first document.

Thanks Sergiu Zaharie.
It's working.
Then how can i returned all the field instead of returning this field only.
{
"_id" : ObjectId("57bd1ff410ea3c38386b9194"),
"locations" : [
{
"loc" : [
103.845061,
1.300626
]
}
]
}
//edit
Solved.
i just clear the projection then it work like charm.
Thank you.

Related

Add field to every document with existing data (move fields data to new field)

I have almost no experience in SQL or noSQL.
I need to update every document so that my fields "Log*" are under the new field "Log"
I found some help from this StackOverflow, but I am still wondering how to move the data.
Thank you very much
Original document
// collection: Services
{
"_id" : ObjectId("5ccb4f99f4953d4894acbe79"),
"Name" : "WebAPI",
"LogPath" : "Product\\APIService\\",
"LogTypeList" : [
{
"Name" : "ApiComCounter",
"FileName" : "ApiComCounter.log"
},
{
"Name" : "ApiService",
"FileName" : "ApiService.log"
}
]
}
Final Document
// collection: Services
{
"_id" : ObjectId("5ccb6fa2ae8f8a5d7037a5dd"),
"Name" : "InvoicingService",
"Log" : {
"LogPath" : "Product\\APIService\\",
"LogTypeList" : [
{
"Name" : "ApiComCounter",
"FileName" : "ApiComCounter.log"
},
{
"Name" : "ApiService",
"FileName" : "ApiService.log"
}
]
}
}
This requires MongoDB 4.2 or higher:
db.<collection>.updateMany({}, [
{$set: {"Log.LogPath": "$LogPath", "Log.LogTypeList": "$LogTypeList"}},
{$unset: ["LogPath", "LogTypeList"]}
])

mongodb extracting values from array

Following is example of table in mongodb, I have multiple records for companies like this, which I need help with.
I wanted to query the below table wherein using value from company I should be able to retrieve the name of all the cars.
"vehicles" : [
{
"source" : "jeep",
"tag" : [
{
"company" : "toyota",
"name" : "fortuner"
},
{
"company" : "rangerover",
"name" : "discovery"
]
}
]
Thanks...
try this :
db.vehicles.find({tag: {$elemMatch: {company:'toyota'}}}).pretty();
read more here : https://docs.mongodb.com/manual/reference/operator/query/elemMatch/

Mongodb Search nested array elements

I have a below data. Would like to search aclpermissions where any of the elements (CRT, READ, DLT, UPD) will match to an array of inputs.
Below query
db.AMSAppACL.find({"aclpermissions.READ" : {'$in': ['58dc0bea0cd182789fc62fab']}}).pretty();
only searches READ element. Is there any way to search all the elements instead of using or queries and aggregate
{
"_id" : ObjectId("5900d6abb9eb284a78f5a350"),
"_class" : "com.debopam.amsapp.model.AMSAppACL",
"attrUniqueCode" : "USER",
"attributeVersion" : 1,
"aclpermissions" : {
"CRT" : [
"58dc0bd70cd182789fc62faa"
],
"READ" : [
"58dc0bd70cd182789fc62faa",
"58dc0bea0cd182789fc62fab"
],
"UPD" : [
"58dc0bd70cd182789fc62faa"
],
"DLT" : [
"58dc0bd70cd182789fc62faa"
]
},
"orgHierachyIdentifier" : "14",
"orgid" : 14,
"createDate" : ISODate("2017-04-26T17:19:39.026Z"),
"lastModifiedDate" : ISODate("2017-04-26T17:19:39.026Z"),
"createdBy" : "appadmin",
"lastModifiedBy" : "appadmin"
}
You should try updating aclpermissions part of schema from dynamic keys to labeled keys.
"aclpermissions":
[
{k:"CRT", v: ["58dc0bd70cd182789fc62faa"]},
{k:"READ", v: [ "58dc0bd70cd182789fc62faa", "58dc0bea0cd182789fc62fab"]}....
]
Now you can update the query from post to something like
db.AMSAppACL.find({"aclpermissions.v" : {'$in': ['58dc0bea0cd182789fc62fab']}}).pretty();

Error in mongodb query to get movie based on id

> db.movmodels.findOne()
{
"_id" : ObjectId("55320b0e0e9e0d9d0540593c"),
"username" : "punk",
"favMovies" : [
{
"alternate_ids" : {
"imdb" : "0137523"
},
"abridged_cast" : [
{
"characters" : [
"Tyler"
],
"id" : "162652627",
"name" : "Brad Pitt"
},
{
"characters" : [
"Narrator"
],
"id" : "162660884",
"name" : "Edward Norton"
},
{
"characters" : [
"Robert"
],
"id" : "162676383",
"name" : "Meat Loaf"
},
{
"characters" : [
"Angel Face"
],
"id" : "162653925",
"name" : "Jared Leto"
},
{
"characters" : [
"Boss"
],
"id" : "770706064",
"name" : "Zach Grenier"
}
],
"synopsis" : "",
"ratings" : {
"audience_score" : 96,
"audience_rating" : "Upright",
"critics_score" : 80,
"critics_rating" : "Certified Fresh"
},
"release_dates" : {
"dvd" : "2000-06-06",
"theater" : "1999-10-15"
},
"critics_consensus" : "",
"runtime" : 139,
"mpaa_rating" : "R",
"year" : 1999,
"title" : "Fight Club",
**"id" : "13153"**
}
],
"__v" : 0
}
This is my data in mongodb.
As I am new to mongodb I wanted to know query to get movie with a particular id.
The query that I tried is. I need to get the movie based on id so that I can remove it from my database
db.movmodels.findOne({username:"punk"},{favMovies:{id:13153}})
but this gives me error.
2015-04-18T05:41:26.221-0400 E QUERY Error: error: {
"$err" : "Can't canonicalize query: BadValue ported projection option: favMovies: { id: 13153.0 }",
"code" : 17287
}
at Error (<anonymous>)
at DBQuery.next (src/mongo/shell/query.js:259:15)
at DBCollection.findOne (src/mongo/shell/collection.js:188:22)
at (shell):1:14 at src/mongo/shell/query.js:259
There are several problems with your query:
The second parameter to find() is a projection, not part of the query. What you want is to supply one document for the query that has two properties: {"username" : "punk", favMovies : { ... } }
However, you also don't want to compare the entire sub-document favMovies, but you only want to match on one of its properties, the id, which requires to 'reach into the object' using the dot operator: {username:"punk", "favMovies.id" : 13153}.
However, that will probably not work yet, because 13153 is not the same as "13153", the latter being a string while the former is a number in JSON.
db.movmodels.findOne({username:"punk", "favMovies.id" : "13153"})
Keep in mind, however, that this will find the entire document for the user named "punk". I'm not sure what exactly your data structure should look like, but it appears you'll have to $pull the movie from the user. In general, I'd say you're embedding too much data into the user, but that's hard to tell without knowing the exact use case.
Here you go:
If you just wanted to get first user who has this fav movie:
db.movmodels.findOne({"favMovies.id": 13153});
And, if you want to know if that user has that movie as favorite.
db.movmodels.findOne({"favMovies.id": 13153, username:"punk"});
Second argument in the findOne is used to only return particular field.
You can use also $elemMatch projection operator (not to be confused with the $elemMatch query operator)
db.movmodels.find({username:"punk"},{favMovies:{$elemMatch:{id:"13153"}}});
`
If you want to find a movie that has another movie (with id 13153) in 'favMovies' array, then write the query as below:
db.movmodels.findOne({username:"punk",'favMovies.id':13153})
And if you want to find a movie with _id 55320b0e0e9e0d9d0540593cwrite the following query:
db.movmodels.findOne({username:"punk",'_id':ObjectId("55320b0e0e9e0d9d0540593c")})

Mongodb + Mongoose: trying to add a sub-sub-item

Does this makes any sense when trying to add a sub-sub-item? (I'm new to mongo - be merciful :-))
question = db.questions.findOne({_id: ObjectId("529c5d44211c9a8c11000006")})
question.answers[0].votes.insert(...)
When I run this from the mongo console the result is an error saying [object object] does not have the method insert.
I have the following mongoDB Question Schema.
{
"__v" : 2,
"_creator" : ObjectId("529c5d2d211c9a8c11000005"),
"_id" : ObjectId("529c5d44211c9a8c11000006"),
"answers" : [
{
"postDate" : ISODate("2013-12-02T10:14:19.060Z"),
"postDateText" : "15min ago",
"authorEmail" : "guys#pix.com",
"authorName" : "guys#pix.com",
"body" : "You need magic powder",
"isWinner" : false,
"_creator" : ObjectId("529c5d2d211c9a8c11000005"),
"_id" : ObjectId("529c5d7b211c9a8c11000008"),
"votes" : [
{
"voteType" : "up",
"_creator" : ObjectId("529c5d2d211c9a8c11000005"),
"_id" : ObjectId("529c5d5b211c9a8c11000007")
}
]
}
],
"authorEmail" : "guys#wix.com",
"authorName" : "guys#wix.com",
"body" : "I'm trying to fly...\n\n<pre class=\"brush: js;\">\nfunction logName(name) {\n console.log(name);\n}\n</pre>",
"isResolved" : false,
"postDate" : ISODate("2013-12-02T10:13:24.235Z"),
"tags" : [
"fly"
],
"title" : "How do I fly?",
"views" : [],
"votes" : [
{
"voteType" : "up",
"_creator" : ObjectId("529c5d2d211c9a8c11000005"),
"_id" : ObjectId("529c5d5b211c9a8c11000007")
}
]
}
I'm trying, given a questionId and an answerId to add a vote to the votes array (which is inside the answer). I can't seem to do it. Help?
insert is for adding whole new documents; when you just want to add a new element to an array field of an existing document, you can use update along with an operator like $push.
So, in the shell you would use something like this:
db.questions.update(
{_id: ObjectId("529c5d44211c9a8c11000006")},
{'answers.0.votes': {$push: voteToPush}})