Sample Data in mongodb collection attached as image.
Query with sort and limit.
Same Data Getting populated in multiple result set.
Page 1 ->Query
db.user_profile.find({},{ email: 1}).skip(0).limit(3).sort( {isEnabled:-1,firstName:1} )
Page 2 ->Query
db.user_profile.find({},{ email: 1}).skip(3).limit(3).sort( {isEnabled:-1,firstName:1} )
Page 3 ->Query
db.user_profile.find({},{ email: 1}).skip(6).limit(3).sort( {isEnabled:-1,firstName:1} )
You Need to project what you are sorting. One way to do it is:
db.user_profile.find({},{ email: 1, isEnabled: 1, firstName:1}).skip(3).limit(3).sort( {isEnabled:-1,firstName:1} )
Notice the projection of isEnabled and firstName that were missing before. This is a simple query but will result in adding two more fields to the output.
If you want to return only the email, you can use an aggregation pipeline that will remove the projection on a latter stage:
db.user_profile.aggregate([
{
$sort: {isEnabled: -1, firstName: 1}
},
{$skip: 0},
{$limit: 3},
{$project: {email: 1}} // or {$project: {email: 1, _id: 0}}
])
You can see the aggregation example working on the playground
Related
I have following document:
user{
_id: objId(..),
name: "John Doe",
transactions:[
{
_id: 1,
amount: 10.00
item_id: 123,
condition: SUCCESS
},
{
_id: 2,
amount: 5.00
item_id: 124,
condition: FAILED
}
..
]
..
}
I tried placing a partial index for failed transactions using:
db.user.createIndex(
{ "transactions.condition": 1 },
{ partialFilterExpression: {"transactions.condition": "FAILED"} }
)
But whenever I do a query or $match through aggregate pipeline with followiing:
{$match: {"transactions": {$elemMatch: {"condition": "FAILED"}}}}
I always get a full document scan COLLSCAN with explain(). I am guessing the filter needs to strictly to follow expression of transactions.condition: "FAILED", but I thought {"transactions": {$elemMatch: {"condition": "FAILED"}}} was identicial to transactions.condition: "FAILED" if you just do one expression. What am I missing here?
Yes, try this instead:
db.user.explain().aggregate({$match: {"transactions.condition": "FAILED"}})
The reason is that MongoDB doesn't build the index for you. It has to be a key.
You'll get a even faster query if you can reduce it to:
db.user.explain().aggregate([
{$match: {"transactions.condition": "FAILED"}},
{$project:{_id:0, transactions.condition:1}}
])
but that may not be the case here.
I have read the docs and still not quite following it. According to it, it returns me specific documents according to my own specifications inside a collection. For grouping, it pretty much says the same thing: "Groups documents by some specified expression and outputs to the next stage a document for each distinct grouping"
So, what does this following code is actually doing? It seems redundant to me.
BillingCycle.aggregate([{
$project: {credit: {$sum: "$credits.value"}, debt: {$sum: "debts.value"}}
}, {
$group: {
_id: null,
credit: {$sum: "$credit"}, debt: {$sum: "debt"}
}
}, {
$project: {_id: 0, credit: 1, debt: 1 }
}]});
"Groups documents by some specified expression and outputs to the next stage a document for each distinct grouping"
The purpose of $group is not only to push some fields to next stage but to gather some element on the basis of input criteria passed in the _id attribute.
On the other, hand $project function will exclude/include some field(or custom field) to next stage. As per document you can see the definition "Passes along the documents with the requested fields to the next stage in the pipeline. The specified fields can be existing fields from the input documents or newly computed fields."
There is one case if we suppress the _id from $group then it will calculate accumulated values for all the input documents as a whole. Which seems to act like $project.
For the query on $project stage is redundant
BillingCycle.aggregate([ {
$group: {
_id: null,
credit: {$sum: "$credit.value"}, debt: {$sum: "debt.value"}
}
}, {
$project: {_id: 0, credit: 1, debt: 1 }
}]});
I am new to Mongo. Posting this question because i am not sure how to search this on google
i have a book documents like below
{
bookId: 1
title: 'some title',
publicationDate: DD-MM-YYYY,
editions: [{
editionId: 1
},{
editionId: 2
}]
}
and another one like this
{
bookId: 2
title: 'some title 2',
publicationDate: DD-MM-YYYY,
editions: [{
editionId: 1
},{
editionId: 1
}]
}
I want to write a query db.books.find({}) which would return only those books where editions.editionId has been duplicated for a book.
So in this example, for bookId: 2 there are two editions with the editionId:1.
Any suggestions?
You can use the aggregation framework; specifically, you can use the $group operator to group the records together by book and edition id, and count how many times they occur : if the count is greater than 1, then you've found a duplication.
Here is an example:
db.books.aggregate([
{$unwind: "$editions"},
{$group: {"_id": {"_id": "$_id", "editionId": "$editions.editionId"}, "count": {$sum: 1}}},
{$match: {"count" : {"$gt": 1}}}
])
Note that this does not return the entire book records, but it does return their identifiers; you can then use these in a subsequent query to fetch the entire records, or do some de-duplication for example.
I got the following query:
query =
{
application: application,
creationTime:{
$gte: start_date.valueOf(),
$lte: end_date.valueOf()
}
},
{
application: 1,
creationTime: 1,
buildSystem: 1,
_id:1
}
var ut_data = db.my_collection.find(query).sort({ _id: -1 }).forEach(function(doc) {print(doc.testStatus)})
Where I want to limit the fields in the result to application, creationTime and buildSystem, to not load the whole documents matching the condition.
Once I print testStatus, it seems like is also available, moreover all fields are available. How can I limit the fields in the result?
(I also tried: {fields:{application: 1, creationTime: 1, buildSystem: 1, _id: 1}} as proposed in Limit Field in Mongodb find() query not working
)
I was passing the two parameters of the query wrongly, so the second part was not considered, I fixed it like this:
query =
[{
application: application,
creationTime:{
$gte: start_date.valueOf(),
$lte: end_date.valueOf()
}
},
{
_id: 1,
application: 1,
creationTime: 1,
buildSystem: 1,
}]
And then, passing each argument separately:
db.my_collection.find(query[0], query[1]).sort({ _id: -1 }).forEach(function(doc) {print(doc.testStatus)})
Or simply passing the query directly to the find method (w/o variables).
I want to be able to retrieve a list of documents matching an id and trace the results back to a specific key.
Example:
// I have these objects:
[{_id: 1, group: 'a'}, {_id: 2, group: 'b'}, {_id: 1, group: 'c'}]
// and these database documents:
{_id: 1}, {_id:2}
I want to create a query that would return essentially {_id: 1}, {_id: 2}, {_id: 1}, or any other result where I can map back the find result to the 'group' property of the original objects.
The problem I run into is that if the list of id contains duplicates or keys not found in the target collection, I lose ordering and can't map the query result back to my objects.
I thought $group could achieve this, but I haven't been able to achieve this so far.
To get a list of all documents matching an id, wouldn't a simple find work?
db.collection.find({"_id":1})