I'm trying to reach something like this:
I have collections of activities that belong to some user.
I want to get the activity names distincted ordered by 'added_time', so I used 'group by' on the activity name and get the max value of 'added_time'.
Also, I want to sort them by 'added_time', and then to get the whole document.
The only thing that I reached so far, is to get only the name that I grouped by, and the 'added_time' property.
This is the query:
db.getCollection('user_activities').aggregate
(
{$match: {'type': 'food', 'user_id': '123'}},
{$group:{'_id':'$name', 'added_time':{$max:'$added_time'}}},
{$sort:{'added_time':-1}},
{$project: {_id: 0,name: "$_id",count: 1,sum: 1, 'added_time': 1}}
)
Can someone help me with reaching the whole document?
Thank's!
Related
Say I have a Foo document like the following:
{
_id: 1,
bar: [{_id: 1, ...bar props}, {_id: 2, ...bar props}, {_id: 3, ...bar props)}],
... other foo props
}
How do I query the database for a single Bar, such that my result looks like:
{_id: 2, ...bar props}
Something like:
db().collection('foo').findOne({ _id: 1, {foo: _id: 2}}, {foo: 1, _id: 0})
Matching and projection are separate operations in MongoDB and you should also keep them separate when you are thinking (and asking) about queries.
You cannot "query for a single Bar". Queries always match documents. What you can do is find a document which contains a Bar which matches conditions, or you can find a document which contains exactly one Bar which also matches conditions, etc. In all of these cases you still get the top-level document(s) as a result.
To retrieve (only) one, several or all of the Bars in whichever documents matched your query conditions, instead of those documents, use projection (either second argument to find or $project aggregation pipeline stage).
When you are using the aggregation pipeline, you can mix $match and $project stages so that, for example, you $match to filter down documents, then $project to reduce the documents to some of their fields, then $match to further filter down the resulting documents, and so on. Still matching and projection are separate operations.
In a mongoDB bd, I need to find all the records where those records aren't in a different collection
Say I have 2 collections
1) user_autos
{
make: string,
user_id: objId
}
2) auto_makes
{
mfg: string,
make: string
}
I need to find all the "makes" that are not part of the "master makes" list
I want to do the parallel to this SQL
SELECT DISTINCT
a.make
FROM
user_autos a
WHERE
a.make NOT IN (
SELECT DISTINCT
b.make
FROM
auto_makes b
)
Help please
to achieve this, you need to make use of aggragation with pipeline stage 'lookup'.
lookup does left join between two collections. so, obviously the unmatching documents of
'user_autos' gives an empty nested array 'auto_makes'. and then 'group' the 'user_autos'
with 'make'. so that a list of 'user_auto' documents will be resulted.
you can do it as below.
db.user_autos.aggregate([
{$lookup:{
from:"äuto_makes",
localField:"make",
foreignField:"make",
as:"m"
}},
{$match:{
m:{$exists:false}
}},
{$group:{
_id:"$make"
}}
//if you want to get the distinct 'make' values as an array of single
//document, add another $group stage.
{$group:{
_id:"",
make_list:{$addToSet:"$_id"}
}}
])
Visit https://docs.mongodb.com/manual/reference/operator/aggregation/group/ ,
https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/
I have a problem in mongodb.
I want to create aggregation witch result will be like this:
A 10
B 2
C 4
D 9
E 3
...
I have a column words in my table and I want to group my records according to first character of column words.
I find resolve for sql but not for mongo.
I will be very grateful for your help
You don't show what the docs in your collection look like, but you can use the aggregate collection method to do this:
// Group by the first letter of the 'words' field of each doc in the 'test'
// collection while generating a count of the docs in each group.
db.test.aggregate({$group: {_id: {$substr: ['$words', 0, 1]}, count: {$sum: 1}}})
I do much find requests on collection like this:
{'$and': [{'time': {'$lt': 1375214400}},
{'time': {'$gte': 1375128000}},
{'$or': [{'uuid': 'test'},{'uuid': 'test2'}]}
]}
Which index i must create: compound or two single or both?
uuid - name of data collector.
time - timestamp
I want to retrieve data, collected by one or few collectors in specified time interval.
Your query would be better written without the $and and using $in instead of $or:
{
'time': {'$lt': 1375214400, '$gte': 1375128000},
'uuid': {'$in': ['test', 'test2']}
}
Then it's pretty clear you need a compound index that covers both time and uuid for best query performance. But it's important to always confirm your index is being used as you expect by using explain().
I am familiar with the best practice of range based pagination on large MongoDB collections, however I am struggling with figuring out how to paginate a collection where the sort value is on a non-unique field.
For example, I have a large collection of users, and there is a field for the number of times they have done something. This field is defintely non-unique, and could have large groups of documents that have the same value.
I would like to return results sorted by that 'numTimesDoneSomething' field.
Here is a sample data set:
{_id: ObjectId("50c480d81ff137e805000003"), numTimesDoneSomething: 12}
{_id: ObjectId("50c480d81ff137e805000005"), numTimesDoneSomething: 9}
{_id: ObjectId("50c480d81ff137e805000006"), numTimesDoneSomething: 7}
{_id: ObjectId("50c480d81ff137e805000007"), numTimesDoneSomething: 1}
{_id: ObjectId("50c480d81ff137e805000002"), numTimesDoneSomething: 15}
{_id: ObjectId("50c480d81ff137e805000008"), numTimesDoneSomething: 1}
{_id: ObjectId("50c480d81ff137e805000009"), numTimesDoneSomething: 1}
{_id: ObjectId("50c480d81ff137e805000004"), numTimesDoneSomething: 12}
{_id: ObjectId("50c480d81ff137e805000010"), numTimesDoneSomething: 1}
{_id: ObjectId("50c480d81ff137e805000011"), numTimesDoneSomething: 1}
How would I return this data set sorted by 'numTimesDoneSomething' with 2 records per page?
#cubbuk shows a good example using offset (skip) but you can also mould the query he shows for ranged pagination as well:
db.collection.find().sort({numTimesDoneSomething:-1, _id:1})
Since the _id here will be unique and you are seconding on it you can actually then range by _id and the results, even between two records having numTimesDoneSomething of 12, should be consistent as to whether they should be on one page or the next.
So doing something as simple as
var q = db.collection.find({_id: {$gt: last_id}}).sort({numTimesDoneSomething:-1, _id:1}).limit(2)
Should work quite good for ranged pagination.
You can sort on multiple fields in this case sort on numTimesDoneSomething and id field. Since id_ field is ascending in itself already according to the insertion timestamp, you will able to paginate through the collection without iterating over duplicate data unless new data is inserted during the iteration.
db.collection.find().sort({numTimesDoneSomething:-1, _id:1}).offset(index).limit(2)