MongoDB query to show a column within an array - mongodb

I wanted to display the grade and date from the database provided to me which is lists of restaurants within New York and its boroughs. I can show the grades but when I try to show the dates that are greater than 2012, I'm having trouble.
Here's the query that I used:
db.restaurants.find(
{
'grades.0.grade': 'A',
'grades.1.grade': 'A',
'grades.2.grade': 'A',
'grades.0.date': { $gt: 2013 },
},
{ borough: 1, cuisine: 1, name: 1, grades: 1, 'grades.grade': 1 }
);
How do I show them in a query?
EDIT: Here's the value within one cell of the date column: "2014-04-21T00:00:00.000+0000".

Related

Mongoose $sort doesn't work when it's before a populate stage in aggregation pipeline

I have the following Author schema, where an author can rate other authors:
{
name: String,
birthDate: Date,
otherAuthorRatings: {
type:
[
{
author: {
type: mongoose.Schema.Types.ObjectId,
ref: "Author",
},
rating: {
type: Number,
},
},
],
}
}
I have an aggregation pipeline in which I'm populating the author property in the otherAuthorRatings, which goes through 3 stages, unwind, lookup and group according to this documentation.
Along with this, I want to sort the authors based on their birthDate, skip some elements and limit to a particular number of elements.
My question:-
When I add the sort, skip and limit stages after the population stage, the query works perfectly, but the $sort stage does not work correctly(i.e., returns random values instead of sorted values) when the sort, skip and limit stages are before the populate stage.
I specifically want that the sort, skip and limit stages be before the populate stage because I want to limit the populate stage to certain number of documents and also to use an index(which I cannot use if the sort stage is after the unwind, lookup and group stages).
Is there a particular reason why this happens? Any solution to this?
EDIT 1:-
I'm trying to sort the outer document, not the properties within the populated entries. Sample docs:-
{
_id: 1,
name: "foo",
birthDate: "2022-12-24T00:00:00.000+00:00",
otherAuthorRatings: [
{
author: 3,
rating: 5
}
],
},
{
_id: 2,
name: "bar",
birthDate: "2022-12-25T00:00:00.000+00:00",
otherAuthorRatings: [
{
author: 1,
rating: 4
},
{
author: 3,
rating: 5
},
],
},
{
_id: 3
name: "baz",
birthDate: "2022-12-26T00:00:00.000+00:00",
otherAuthorRatings: [],
},
I want that the author with the birthdate of 24th December arrive before the author with the birthdate of 25th December and 26th December(or reverse if I sort it in descending order). I don't use the populated fields within the embedded document for sorting.
Solution:
Turns out that the group stage messes with the order(I believe this is normal) of transactions. So I had to re-sort the result after the group stage. This wasn't very costly because the sort was happening on a limited number of elements.

How does unordered insertion behave in db.collections.insert() in mongodb

db.products.insert(
[
{ _id: 20, item: "lamp", qty: 50, type: "desk" },
{ _id: 21, item: "lamp", qty: twenty, type: "floor" },
{ _id: 22, item: "bulk", qty: 100 }
],
{ ordered: false }
)
I am trying to insert three documents in the collection products, but the second document has an error, the qty field has erroneous value. I am using ordered: false so I am expecting that all the other documents should get inserted except the second one, but this is not the case, none of the documents get inserted.
Then what is the difference between ordered and unordered insertion? How can I achieve the desired results in this case.
Ordered/unordered inserts are distinguished on the server side.
If you don't have the twenty variable defined, the error happens on the client side and no insert is attempted at all.

MongoDB - Filter on First Field of a Two Field Compound Index and Sort on the Second Field?

I am inserting data into my MongoDB collection of the following format.
{'customer_id': 1, 'timestamp': 200}
{'customer_id': 2, 'timestamp': 210}
{'customer_id': 3, 'timestamp': 300}
I have a compound index created with keys: { 'customer_id': 1, 'timestamp': -1 }
db.collection.createIndex( { customer_id: 1, timestamp: -1 } , { name: "query for inventory" } )
Now, I need to filter such that I get the documents with customer_id = 1 or 2 and then sort the documents on the timestamp (in descending format, that is the latest will be at the top).
My query looks like this:
db.collection.find( { 'customer_id': { '$in': [ 1, 2 ] } } ).sort( { 'timestamp': -1 } ).limit( 100 )
I know how to do the query but I am unsure if I should be using this Compound Index or using two Indices on the separate fields or both.
It would be really helpful if I could get a clarification on which approach to use and why that approach is better.

Mongodb: Get last item from array in document

I have a collection in MongoDB with elements looking like this
{
userId: 'X',
access: [
{ deviceId: 'a', time: "A timestamp" },
{ deviceId: 'b', time: "Another timestamp" },
]
}
I want to match documents based on userId and then I want to get the last element in the access array. The value I am most interested in here for user with id "X" is "Another timestamp".
I do not want mongodb to return the entire document, just that last element and always the last one.
How can I write a query/aggregation that solves this?
Try using $slice:
db.collection.find({ userId: 'value' }, { access: { $slice: -1 } } )

mongodb: order and limit the collection, then order and limit the resulting document nested documents

I have the following data structure on my game collection:
{
name: game1
date: 2010-10-10
media: [{
id: 1,
created: 2010-10-10 00:00:59
}, {
id: 2,
created: 2010-10-10 00:00:30
}]
},
{
name: game2
date: 2010-10-09
media: [{
id: 1,
created: 2010-10-09 00:10:40
}, {
id: 2,
created: 2010-10-09 09:01:00
}]
}
I want to get the game with the highest date, then get the related media with the highest created to get it's id. In the example above, the result would be
{
name: game1
date: 2010-10-10
media: [{
id: 1,
created: 2010-10-10 00:00:59
}]
}
I tried to use the find and find_one, and also aggregation, but I could not figure a way to make this query.
Any suggestions?
You will need to $unwind the media array in order to get the subdocument in that array where created is the highest then you $sort your documents by date and created all in descending order. Use $limit to output n documents which is 1 in our case.
In [26]: import pymongo
In [27]: conn = pymongo.MongoClient()
In [28]: db = conn.test
In [29]: col = db.gamers
In [30]: list(col.aggregate([{"$unwind": "$media"}, {"$sort": {"date": -1, "media.created": -1}}, {"$limit": 1}]))
Out[30]:
[{'_id': ObjectId('553323ec0acf450bc6b7438c'),
'date': '2010-10-10',
'media': {'created': '2010-10-10 00:00:59', 'id': 1},
'name': 'game1'
}]