This question already has answers here:
Select Max() with "group by" in mongodb
(4 answers)
Closed 6 years ago.
Imagine I have a MongoDB collection such as the following, where each row corresponds to a document:
{name:'rick', age:30}
{name:'john', age:40}
{name:'rick', age:35}
{name:'john', age:20}
{name:'jeff', age:50}
{name:'jeff', age:40}
Some documents have the "name" field set to the same value (2 ricks, 2 johns and 2 jeffs). If two or more documents have the "name" field set to the same value, of these I want to select only the document with the highest age. Like this:
{name:'rick', age:35}
{name:'john', age:40}
{name:'jeff', age:50}
Is there a rick aged 30 and a rick aged 35? I select rick aged 35! And so on...
But how can the query look like?
db.getCollection('Mytest').aggregate({$group:{_id:{"name":"$name"}, age: { $max: "$age" }}})
Output:
{
"_id" : {
"name" : "jeff"
},
"age" : 50
}
/* 2 */
{
"_id" : {
"name" : "john"
},
"age" : 40
}
/* 3 */
{
"_id" : {
"name" : "rick"
},
"age" : 35
}
db.collection.aggregate([{$group:{_id:"$name",sal:{$max:"$age"}}}]);
Related
I have mongo document like this:
{
"pw" : [
{
"id" : 123,
"qty" : 10
},
{
"id" : 456,
"qty" : 15
}
]
}
Id and qty is Number type in Atlas Search.
I want to search like "id = 123" and qty > 5.
I USED EQUALS and RANGE operator for this, but it is not working. How can I set criteria for specific document level (not in array level)?
This question already has answers here:
Updating a Nested Array with MongoDB
(2 answers)
Closed 5 years ago.
Following is a MongoDB document:
{
"_id" : 2,
"mem_id" : M002,
"email" : "xyz#gmail.com",
"event_type" : [
{
"name" : "MT",
"count" : 1,
"language" : [
{
"name" : "English",
"count" : 1,
"genre" : [
{
"name" : "Action",
"count" : 6
},
{
"name" : "Sci-Fi",
"count" : 3
}
],
"cast" : [
{
"name" : "Sam Wortington",
"count" : 2
},
{
"name" : "Bruce Willis",
"count" : 4
},
{
"name" : "Will Smith",
"count" : 7
},
{
"name" : "Irfan Khan",
"count" : 1
}
]
}
]
}
]
}
I'm not able to update fields that is of type array, specially event_type, language, genre and cast because of nesting. Basically, I wanted to update all the four mentioned fields along with count field for each and subdocuments. The update statement should insert a value to the tree if the value is new else should increment the count for that value.
What can be the query in mongo shell?
Thanks
You are directly hitting one of the current limitations of MongoDB.
The problem is that the engine does not support several positional operators.
See this Multiple use of the positional `$` operator to update nested arrays
There is an open ticket for this: https://jira.mongodb.org/browse/SERVER-831 (mentioned also there)
You can also read this one on how to change your data model: Updating nested arrays in mongodb
If it is feasible for you, you can do:
db.collection.update({_id:2,"event_type.name":'MT' ,"event_type.language.name":'English'},{$set:{"event_type.0.language.$.count":<number>}})
db.collection.update({_id:2,"event_type.name":'MT' ,"event_type.language.name":'English'},{$set:{"event_type.$.language.0.count":<number>}})
But you cannot do:
db.collection.update({_id:2,"event_type.name":'MT' ,"event_type.language.name":'English'},{$set:{"event_type.$.language.$.count":<number>}})
Let's take case by case:
To update the field name in event_type array:
db.testnested.update({"event_type.name" : "MT"}, {$set : {"event_type.name" : "GMT"}})
This command will update the name for an object inside the event_type list, to GMT from MT:
BEFORE:
db.testnested.find({}, {"event_type.name" : 1})
{ "_id" : 2, "event_type" : [ { "name" : "MT" } ] }
AFTER:
db.testnested.find({}, {"event_type.name" : 1})
{ "_id" : 2, "event_type" : [ { "name" : "GMT" } ] }
2.To update fields inside event_type, such as language, genre that are intern list:
There is no direct query for this. You need to read the document, update that document using the JavaScript or language of your choice, and then save() the same. I dont think there is any other way available till mongo 2.4
For further documentation, you can refer to save().
Thanks!
This question already has answers here:
rank leaderboard in mongo with surrounding players
(2 answers)
Closed 3 years ago.
I have a collection of users, each user has a points attribute (see schema below).
My end goal is to return a sorted array of limited documents according to a specific user location, or in other words, a small part of a leaderboard relative for a specific user location.
Currently I query and sort all users, find the user I want in the returned array and slice the array according to that. I was wondering if there is a query that will save me returning all users.
Sample User Schema:
/* 1 */
{
"_id" : ObjectId("..."),
"points" : 5852 ,
"key" : "user1"
}
/* 2 */
{
"_id" : ObjectId("..."),
"points" : 3835,
"key" : "user2"
}
/* 3 */
{
"_id" : ObjectId("..."),
"points" : 1984,
"key" : "user3"
}
/* 4 */
{
"_id" : ObjectId("...."),
"points" : 2437,
"key" : "user4"
}
Lets assume I want the query to return 3 documents sorted by points -
The document of "user4" (my relative user), the document after him in the leaderboard ("user3" in the example above) and 1 document before him ("user2" in the above example)
Thanks!
Edit: Im using mongoose as well if this simplifies things.
Edit2: Please see below the expected output -
/* 1 */
{
"_id" : ObjectId("..."),
"points" : 3835,
"key" : "user2"
}
/* 2 */
{
"_id" : ObjectId("...."),
"points" : 2437,
"key" : "user4"
}
/* 3 */
{
"_id" : ObjectId("..."),
"points" : 1984,
"key" : "user3"
}
Note that "user1" does not appear in the output as the query asks for 1 user ranked above and 1 user ranked below "user4"
Sounds like you're trying to do this: rank leaderboard in mongo with surrounding players
As it says in the answer to that question, the easiest way to do it is with three queries. Even though that's an increase in the number of queries, the data you transfer will be significantly reduced.
This question already has answers here:
Query for documents where array size is greater than 1
(14 answers)
Closed 7 years ago.
Example document:
{
"aliases" : {
"name" : [
"Brinton McKay",
"Dr. Theopolis",
"Galactic Spiral Sound",
"Highrise",
"Memory Boy",
"Semblance Factor",
"Spy (2)",
"Three O'Clock High"]}
}
How i can count the number of "name" under "aliases"?
I would like to print all _id who which contains more than 3 aliases.
any help would be appreciated.
Please check the below query :
db.collection.find({ $where : function()
{ return Object.keys(this.aliases.name).length > 3 } });
OR
db.collection.aggregate([
{$project : { _id :1 , numb : {$size : "$aliases.name"} }
},
{$match : { numb :{$gt : 3 }}
}
]);
PS : you can see the documentation in below link :
http://docs.mongodb.org/manual/reference/operator/query/where/
This question already has answers here:
How to update the _id of one MongoDB Document?
(7 answers)
Closed 8 years ago.
I have a collection (510 documents) where _id are numbers :
{ "_id" : "1",
"name" : "eric" }
{ "_id" : "2",
"name" : "tom" }
....
and I want to change their values to ObjectId() to be like this:
{ "_id" : ObjectId("53849e258bf3be07804a00d0"),
"name" : "eric" }
{ "_id" : ObjectId("53849e388bf3be07804a00d1"),
"name" : "tom" }
....
so I tried:
db.contacts.find().forEach(function(doc) {
db.contacts.update(
{ "_id": doc._id },
{ "$set": { "_id": ObjectId()} }
);
})
but it doesn't work, I got like result:
Mod on _id not allowed
Thank you.
You cannot change the _id of an Object in a collection once it is created (it is not allowed by mongodb at all). However you could copy the full content of the object execpt of the _id and add your new _id with the ObjectId and insert it into your collection. Afterwards you can remove all the Objects where the _id is a number. It's a bit more complicated but the result is the same (and it works).
Have a look here.