MongoDb Query db.<collectionname>.find() - mongodb

I have this Document for mongodb im working on.
The query i m running is showing no output even though there is
one field with score < 5
{
"address": {
"building": "1007",
"coord": [ -73.856077, 40.848447 ],
"street": "Morris Park Ave",
"zipcode": "10462"
},
"borough": "Bronx",
"cuisine": "Bakery",
"grades": [
{ "date": { "$date": 1393804800000 }, "grade": "A", "score": 2 },
{ "date": { "$date": 1378857600000 }, "grade": "A", "score": 6 },
{ "date": { "$date": 1358985600000 }, "grade": "A", "score": 10 },
{ "date": { "$date": 1322006400000 }, "grade": "A", "score": 9 },
{ "date": { "$date": 1299715200000 }, "grade": "B", "score": 14 }
],
"name": "Morris Park Bake Shop",
"restaurant_id": "30075445"
}
db.rest.find({grades : {"score":{$lt:5}}});

The reason that your query isn't getting the expected result is that you're not quite using the correct syntax for querying a field in an embedded document. The correct syntax is
db.rest.find({ "grades.score" : {$lt:5}})
This syntax uses the dot notation to specify the path to the field in the embedded document that you are querying for.
The syntax you used means something a tad different. It queries for a document that has an embedded document which is an exact match to the document in your query rather than looking for a document that has an embedded document with a field in it that matches your search criteria.
To illustrate the difference, let's assume you also have the following document in the collection.
{
"address": {
"building": "1007",
"coord": [ -73.856077, 40.848447 ],
"street": "Morris Park Ave",
"zipcode": "10462"
},
"borough": "Bronx",
"cuisine": "Bakery",
"grades": [
{ "score": 2 },
{ "score": 6 },
{ "score": 10 },
{ "score": 9 },
{ "score": 14 }
],
"name": "Morris Park Bake Shop",
"restaurant_id": "30075445"
}
If we now run the following query, it finds the second document, and only the second document:
db.rest.find({grades : {"score":2}})
This is because this type of query translates the embedded document you specified as the search criterion into its BSON representation and then looks for an exact match to the supplied document rather than apply the criterion you were looking for to every embedded document that has a 'score' field.
If run the query using the

Related

How to avoid huge json documents in mongoDB

I am new to mongoDB modelling, I have been working in a small app that just used to have one collection with all my data like this:
{
"name": "Thanos",
"age": 999,
"lastName": "whatever",
"subjects": [
{
"name": "algebra",
"mark": 999
},
{
"name": "quemistry",
"mark": 999
},
{
"name": "whatever",
"mark": 999
}
]
}
I know this is standard in mongoDB since we don't have to map relotionships to other collections like in a relational database. My problem is that my app is growing and my json, even tho it works perfectly fine, it is starting to be huge since it has a few more (and quite big) nested fields:
{
"name": "Thanos",
"age": 999,
"lastName": "whatever",
"subjects": [
{
"name": "algebra",
"mark": 999
},
{
"name": "quemistry",
"mark": 999
},
{
"name": "whatever",
"mark": 999
}
],
"tutors": [
{
"name": "John",
"phone": 2000,
"status": "father"
},
{
"name": "Anne",
"phone": 200000,
"status": "mother"
}
],
"exams": [
{
"id": "exam1",
"file": "file"
},
{
"id": "exam2",
"file": "file"
},
{
"id": "exam3",
"file": "file"
}
]
}
notice that I have simplified the json a lot, the nested fields have way more fields. I have two questions:
Is this a proper way to model Mongodb one to many relationships and how do I avoid such long json documents without splitting into more documents?
Isn't it a performance issue that I have to go through all the students just to get subjects for example?

MongoDB query: aggregate with "findOne"

I'm trying to make a query on MongoDB 3.4 where I add a field for one specific element of an array. Example of the object:
{
"_id": 1,
"people": [
{
"name": "Jhon Smith",
"age": "30",
"state": "NY"
},{
"name": "Clint Mercer",
"age": "50",
"state": "NY"
},{
"name": "Walter Smith",
"age": "40",
"state": "WI"
}
]
}
And I want to make a query where I'll add to this document an attribute with the first person with "Smith" in it's name. Example:
{
"_id": 1,
"people": [
{
"name": "Jhon Smith",
"age": "30",
"state": "NY"
},{
"name": "Clint Mercer",
"age": "50",
"state": "NY"
},{
"name": "Walter Smith",
"age": "40",
"state": "WI"
}
],
"firstSmith": {
"name": "Jhon Smith",
"age": "30",
"state": "NY"
}
}
I already have the _id of the document I want, but I can't understand how to make a query like this. I'm trying using aggregate with "$match" for the id and "$addFields" after, but I can't make a query that works for this field to find exactly what I want. I think it would be similar to the "findOne" query, but I can't find anything that works on "$addFields".
Obs: I DON'T want the "firstSmith" to be an array with just one "people" inside, I want it as is in the example.
I'd appreciate some help with this one.
$match - to filter the relevant document
$filter with $regexMatch - to filter people array by the name property
arrayElemAt - to get only the first element of above array
$addFields - to add new field with value from above result
db.collection.aggregate([
{
"$match": {
"_id": 1
}
},
{
"$addFields": {
"firstSmith": {
"$arrayElemAt": [
{
"$filter": {
"input": "$people",
"cond": {
"$regexMatch": {
"input": "$$this.name",
"regex": "Smith"
}
}
}
},
0
]
}
}
}
])
Working example

MongoDB query document that doesn't have a given entry?

I have the following document:
{
"address": {
"building": "1007",
"coord": [ -73.856077, 40.848447 ],
"street": "Morris Park Ave",
"zipcode": "10462"
},
"borough": "Bronx",
"cuisine": "Bakery",
"grades": [
{ "date": { "$date": 1393804800000 }, "grade": "A", "score": 2 },
{ "date": { "$date": 1378857600000 }, "grade": "A", "score": 6 },
{ "date": { "$date": 1358985600000 }, "grade": "A", "score": 10 },
{ "date": { "$date": 1322006400000 }, "grade": "A", "score": 9 },
{ "date": { "$date": 1299715200000 }, "grade": "B", "score": 14 }
],
"name": "Morris Park Bake Shop",
"restaurant_id": "30075445"
}
I want a query that looks at the grades.grade and grades.score and doesn't return a this document if a grades object has grade == "A" AND score == 2. However, I want it to return a document if for example one grades object has grade == "A" and another grades object has score == 2.
This might also illustrate what I'm trying to do (although it doesn't work):
db.restaurants.find({
grades : {
$and: [
{"grade": {'$ne':"A"}},
{"score": {'$ne':2}}
]
}
});
You can try below query.
You basically require $anding $or and $nand. MongoDB doesn't have $nand operator, so I replaced it with the equivalent experession.
db.restaurants.find({
$and: [{
$or: [{
"grades.grade": "A"
}, {
"grades.score": 2
}]
}, {
$nor: [{
$and: [{
"grades.grade": "A"
}, {
"grades.score": 2
}]
}]
}]
});
$or operation will match all documents where any of the grade embedded document has either grade A or score is 2.
{ "grade": "A", "score": 3 } --- Just grade A
{ "grade": "A", "score": 2 } --- Both grade A and score 2
{ "grade": "B", "score": 2 } --- Just score 2
$nand operation will match all the documents where none of the grade embedded documents has both grade as A and score is 2
{ "grade": "A", "score": 3 } --- Just grade A
{ "grade": "B", "score": 2 } --- Just score 2
{ "grade": "C", "score": 4 } --- None
$and of above operations is the intersection.
{ "grade": "A", "score": 3 } --- Just grade A
{ "grade": "B", "score": 2 } --- Just score 2

What's the correct syntax for given mongodb query?

Question: Write a MongoDB query to find the restaurants which locates in latitude value less than -95.754168.
Structure of 'restaurants' collection
{
"address": {
"building": "1007",
"coord": [ -73.856077, 40.848447 ],
"street": "Morris Park Ave",
"zipcode": "10462"
},
"borough": "Bronx",
"cuisine": "Bakery",
"grades": [
{ "date": { "$date": 1393804800000 }, "grade": "A", "score": 2 },
{ "date": { "$date": 1378857600000 }, "grade": "A", "score": 6 },
{ "date": { "$date": 1358985600000 }, "grade": "A", "score": 10 },
{ "date": { "$date": 1322006400000 }, "grade": "A", "score": 9 },
{ "date": { "$date": 1299715200000 }, "grade": "B", "score": 14 }
],
"name": "Morris Park Bake Shop",
"restaurant_id": "30075445"
}
Author's Answer is : db.restaurants.find({"address.coord" : {$lt : -95.754168}});
Is this the correct answer?
If no then what is the correct answer?
Resource: http://www.w3resource.com/mongodb-exercises/#PracticeOnline
You can go into your coord index like this
db.restaurants.find({"address.coord.0" : {$lt: -95.754168}});
According to the documentation here,
MongoDB uses the dot notation to access the elements of an array and to access the fields of an embedded document.
E.g. <array>.<index>
Note that the index is 0-based.

Multi-level sorting or orderBy in mongoDB

I am working on mongoDB with Laravel using jenssegers . and i am trying to get
documents on sorting based on layout.price.
Is this possible in mongodb with laravel. ?
I am using limit and skip for pagination , so i have to get orderBy or sort direct from Database.
[{
"title": "I am first document",
"design": "mango",
"description": "Loremipsum",
"dimension": [
{
"id": "542549383d1784901000002c"
}
],
"layout": [
{
"id": "542411813d17849810000029",
"price": NumberInt(69000)
}, {
"id": "542411813d17849810000030",
"price": NumberInt(2000)
}
],
"images": [
"uploads/sofa/QRSTU695a6_0.png"
],
"product_type": NumberInt(1),
"updated_at": ISODate("2014-10-08T08:47:26.0Z"),
"created_at": ISODate("2014-09-29T11:13:52.0Z")
},
{
"title": "I am second document",
"design": "mango2",
"description": "Loremipsum",
"dimension": [
{
"id": "542549383d1784901000002d"
}
],
"layout": [
{
"id": "542411813d17849810000031",
"price": NumberInt(80000)
}, {
"id": "542411813d17849810000032",
"price": NumberInt(27000)
}
],
"images": [
"uploads/sofa/QRSTU695a6_0.png"
],
"product_type": NumberInt(1),
"updated_at": ISODate("2014-10-08T08:47:26.0Z"),
"created_at": ISODate("2014-09-29T11:13:52.0Z")
}]