I am new to mongoDB . I have aware of some basic queries of mongoDb but not advanced.
My document looks like following :
{
"_id" : ObjectId("5289deaa84aedcc100228259"),
"gender" : "male",
"intrest" : [
{
"userId" : ObjectId("5286294984ae18ac5d19af36"),
"timestamp" : ISODate("2013-11-18T09:32:38.040Z"),
"status" : "Pending"
},
{
"userId" : ObjectId("5286295984ae18ac5d19af37"),
"timestamp" : ISODate("2013-11-18T09:33:17.493Z"),
"status" : "Pending"
}
],
"intrestAccepted" : [ ],
"intrestCancled" : [ ],
"intrestDeclined" : [ ],
"intrestReceived" : [
ObjectId("5286294984ae18ac5d19af36"),
ObjectId("5286295984ae18ac5d19af37")
],
"owner" : ObjectId("5286293284ae18ac5d19af35"),
"postDesc" : "gggg",
"tags" : [
"ggg"
]
}
{
"_id" : ObjectId("5289dea084aedcc100228258"),
"gender" : "female",
"intrest" : [
{
"userId" : ObjectId("5286294984ae18ac5d19af36"),
"timestamp" : ISODate("2013-11-18T09:32:42.934Z"),
"status" : "Pending"
},
{
"userId" : ObjectId("5286295984ae18ac5d19af37"),
"timestamp" : ISODate("2013-11-18T09:33:18.520Z"),
"status" : "Pending"
}
],
"intrestAccepted" : [ ],
"intrestCancled" : [ ],
"intrestDeclined" : [ ],
"intrestReceived" : [
ObjectId("5286294984ae18ac5d19af36"),
ObjectId("5286295984ae18ac5d19af37")
],
"owner" : ObjectId("5286293284ae18ac5d19af35"),
"postDesc" : "asdf",
"tags" : [
"asdf"
]
}
{
"_id" : ObjectId("5289dec984aedcc10022825a"),
"gender" : "male",
"intrest" : [
{
"userId" : ObjectId("5286295984ae18ac5d19af37"),
"timestamp" : ISODate("2013-11-18T09:33:20.996Z"),
"status" : "Pending"
}
],
"intrestAccepted" : [ ],
"intrestCancled" : [ ],
"intrestDeclined" : [ ],
"intrestReceived" : [
ObjectId("5286295984ae18ac5d19af37")
],
"owner" : ObjectId("5286294984ae18ac5d19af36"),
"postDesc" : "fff",
"tags" : [
"fff"
]
}
I want to find totalcount for intrestReceived[] whose owner is ObjectId("5286293284ae18ac5d19af35")
What query am I supposed to write. Please help .
You could try something simple like this:
intrestReceived_length = 0
db.col.find({ _id: ObjectId("5286293284ae18ac5d19af35") }).forEach( function( doc ){
intrestReceived_length = doc.intrestReceived.length;
});
The find will extract only the document that matches the ObjectId you provided and then we use a forEach on the cursor to iterate over all of the (one) results. Within the forEach callback, we just use a JavaScript array.length command to extract the size of the array.
You could also output only the intrestReceived array by providing a projection in your find command:
db.col.find({ _id: ObjectId("5286293284ae18ac5d19af35") }, { "intrestReceived": 1 })...
This will return the same document but it will only contain the _id and intrestReceived attributes.
Related
We have following structure in our Mongo collection
{
"_id" : ObjectId("5f98aeadbaf1ea001affe4c0"),
"name" : "Temp",
"campaigntype" : 3,
"startdate" : ISODate("2021-01-01T00:00:00.000Z"),
"enddate" : ISODate("2021-01-01T00:00:00.000Z"),
"affiliatetag" : "",
"promotedtitles" : [
{
"primaryisbn" : "9781453238431",
"promoprice" : "1.99",
"countries" : [
"US",
"CA",
"AU",
"GB"
],
"retailers" : [
"ALL"
],
"dlp" : "17.99",
"notes1" : "History",
"notes2" : "",
"sequence" : 1
},
{
"primaryisbn" : "9781504063562",
"promoprice" : "1.99",
"countries" : [
"US",
"CA"
],
"retailers" : [
"ALL"
],
"dlp" : "11.99",
"notes1" : "Thrillers",
"notes2" : "",
"sequence" : 2
},
{
"primaryisbn" : "9781497673984",
"promoprice" : "0.99",
"countries" : [
"US",
"CA"
],
"retailers" : [
"ALL"
],
"dlp" : "6.99",
"notes1" : "Romantic Suspense",
"notes2" : "",
"sequence" : 3
},
{
"primaryisbn" : "9780547526959",
"promoprice" : "1.99",
"countries" : [
"CA"
],
"retailers" : [
"All"
],
"dlp" : "17.99",
"notes1" : "History",
"notes2" : "",
"sequence" : 4
},
{
"primaryisbn" : "9781453274248",
"promoprice" : "1.99",
"countries" : [
"US"
],
"retailers" : [
"All"
],
"dlp" : "9.99",
"notes1" : "Historical Fiction",
"notes2" : "",
"sequence" : 5
}
],
"active" : true,
"createdby" : ObjectId("5d2e2755d3851f0012108a05")
}
We need to write a query by passing single country like ['US'] or multiple country like ['US', 'CA']. Query should only return us matching sub document from promoted titles.
For example, If we pass country as 'US', we should get primary isbn 9781453238431, 9781504063562, 9781497673984 and 9781453274248. If we pass country as ['GB', 'CA'], we need to get 9781453238431, 9781504063562, 9781497673984 and 9780547526959. If we pass ['GB'], we should only get 9781453238431 sub document
We were trying with promotedtitles.countries : {$in : ['US', 'CA']} but that don't work.
Thanks in advance
You can $unwind and $match like this:
$unwind is to deconstruct the array and get every object as a different value instead all together in an array.
Then you can filter each object using $match and $in.
db.collection.aggregate([
{
"$unwind": "$promotedtitles"
},
{
"$match": {
"promotedtitles.countries": {
"$in": [
"US"
]
}
}
},
{
"$project": {
"_id": 0,
"result": "$promotedtitles.primaryisbn"
}
}
])
Example here using US and here with GB, CA.
Also, if you want to get all ISBNs in an array you can add a $group like this example
I have the following document and want to update state
Document ID: ObjectId("5a4e5a448b70d50e34d204a5")
Target ID: ObjectId("5a4e5a438b70d50e34d203ea")
I have no idea how to update the state to e.g. 4
{
"_id" : ObjectId("5a4e5a448b70d50e34d204a5"),
"name" : "Wirtschaftsdienst",
"date" : ISODate("2012-10-07T00:00:00.000Z"),
"comment" : null,
"tasks" : [
{
"name" : "Speisen und Getränke",
"sections" : [
{
"start" : 46800,
"end" : 72000,
"entirely" : true,
"assistants" : [
{
"assistant" : {
"_id" : ObjectId("5a4e5a438b70d50e34d203ea")
},
"state" : 3
},
{
"assistant" : {
"_id" : ObjectId("5a4e5a438b70d50e34d203f4")
},
"state" : 3
}
]
}
]
}
]
}
Use positional operator $[] along with arrayFilters to get your job done!
Try this query:
db.collection.update(
{"_id" : ObjectId("5a4e5a448b70d50e34d204a5")},
{$set: {"tasks.$[].sections.$[].assistants.$[element].state":4}},
{arrayFilters: [ {"element.assistant":{"_id" :
ObjectId("5a4e5a438b70d50e34d203ea")} }
], multi:true}
)
And the output is:
/* 1 */
{
"_id" : ObjectId("5a4e5a448b70d50e34d204a5"),
"name" : "Wirtschaftsdienst",
"date" : ISODate("2012-10-07T00:00:00.000Z"),
"comment" : null,
"tasks" : [
{
"name" : "Speisen und Getränke",
"sections" : [
{
"start" : 46800,
"end" : 72000,
"entirely" : true,
"assistants" : [
{
"assistant" : {
"_id" : ObjectId("5a4e5a438b70d50e34d203ea")
},
"state" : 4.0
},
{
"assistant" : {
"_id" : ObjectId("5a4e5a438b70d50e34d203f4")
},
"state" : 3.0
}
]
}
]
}
]
}
I have this two collection which each document presents a chat session:
{
"_id" : ObjectId("58136ba83bdddd2d3cd4b3fb"),
"Created" : ISODate("2016-10-28T15:15:52.563Z"),
"Messages" : [
{
"Created" : ISODate("2016-10-28T15:15:52.567Z"),
"ReadBy" : [
ObjectId("57c96a14870ae36ede4d8085"),
ObjectId("57c972b6fc8effecde6cf0fa")
],
"Content" : "Hello"
}
]
}
{
"_id" : ObjectId("5813ac380a45415df8e7fc08"),
"Created" : ISODate("2016-10-28T15:16:52.563Z"),
"Messages" : [
{
"Created" : ISODate("2016-10-28T15:15:52.567Z"),
"ReadBy" : [
ObjectId("57c96a14870ae36ede4d8234"),
ObjectId("57c972b6fc8effecde6cf987")
],
"Content" : "Hello2"
}
]
}
I am trying to use $aggregate with $project, and to perform a simple $setIntersection in order to get matching ObjectIds.
This is the projection:
db.getCollection('Chats').aggregate([
{
$project: {
Created: 1,
Messages: 1,
Match: {
$setIntersection: [ "$Messages.ReadBy", [ObjectId("57c96a14870ae36ede4d8085")] ]
},
ReadBy: "$Messages.ReadBy"
}
}
])
The result i am getting from this aggregate, seems to insert "$Messages.ReadBy" into Sub-Array of Array [[ObjectId("....")]] for example.
The Result is that $setIntersection returns null although there is something relevant for me, and the new "ReadBy" field i added for debug shows the problem of sub-array:
{
"_id" : ObjectId("58136ba83bdddd2d3cd4b3fb"),
"Created" : ISODate("2016-10-28T15:15:52.563Z"),
"Messages" : [
{
"Created" : ISODate("2016-10-28T15:15:52.567Z"),
"ReadBy" : [
ObjectId("57c96a14870ae36ede4d8085"),
ObjectId("57c972b6fc8effecde6cf0fa")
],
"Content" : "Hello"
}
],
"Match" : [],
"ReadBy" : [
[
ObjectId("57c96a14870ae36ede4d8085"),
ObjectId("57c972b6fc8effecde6cf0fa")
]
]
}
{
"_id" : ObjectId("5813ac380a45415df8e7fc08"),
"Created" : ISODate("2016-10-28T15:16:52.563Z"),
"Messages" : [
{
"Created" : ISODate("2016-10-28T15:15:52.567Z"),
"ReadBy" : [
ObjectId("57c96a14870ae36ede4d8234"),
ObjectId("57c972b6fc8effecde6cf987")
],
"Content" : "Hello2"
}
],
"Match" : [],
"ReadBy" : [
[
ObjectId("57c96a14870ae36ede4d8234"),
ObjectId("57c972b6fc8effecde6cf987")
]
]
}
Why is "Match" field returns empty array?
And why "ReadBy" wrapping the source field with extra array?
a solution is to use $arrayElemAt to get the sub array.
the new query is
db.getCollection('Chats').aggregate([
{
$project:{
Created:1,
Messages:1,
Match:{
$setIntersection:[
{
$arrayElemAt:[
"$Messages.ReadBy",
0
]
},
[
ObjectId("57c96a14870ae36ede4d8085")
]
]
},
ReadBy:"$Messages.ReadBy"
}
}
])
and the result is now
{
"_id" : ObjectId("58136ba83bdddd2d3cd4b3fb"),
"Created" : ISODate("2016-10-28T15:15:52.563Z"),
"Messages" : [
{
"Created" : ISODate("2016-10-28T15:15:52.567Z"),
"ReadBy" : [
ObjectId("57c96a14870ae36ede4d8085"),
ObjectId("57c972b6fc8effecde6cf0fa")
],
"Content" : "Hello"
}
],
"Match" : [
ObjectId("57c96a14870ae36ede4d8085")
],
"ReadBy" : [
[
ObjectId("57c96a14870ae36ede4d8085"),
ObjectId("57c972b6fc8effecde6cf0fa")
]
]
}
{
"_id" : ObjectId("5813ac380a45415df8e7fc08"),
"Created" : ISODate("2016-10-28T15:16:52.563Z"),
"Messages" : [
{
"Created" : ISODate("2016-10-28T15:15:52.567Z"),
"ReadBy" : [
ObjectId("57c96a14870ae36ede4d8234"),
ObjectId("57c972b6fc8effecde6cf987")
],
"Content" : "Hello2"
}
],
"Match" : [ ],
"ReadBy" : [
[
ObjectId("57c96a14870ae36ede4d8234"),
ObjectId("57c972b6fc8effecde6cf987")
]
]
}
I 'm trying to return a list of unique titles by the same user/author. I used
posts.find(
{'student':user , 'class_number':0}
).sort('created', -1).limit(num).toArray(function(err, items) {
which works well as long as there is a 'class_number':0 which there may not always be. So I tried using distinct but I'm not sure how I can provide a query for unique titles. Is there a better way to do this? Here's some data:
posts.distinct(
{'student':user , 'title':?}
)
.sort('created', -1).limit(num).toArray(function(err, items) {
Data:
{
"_id" : ObjectId("53aa0093e99034914b000003"),
"ans" : 1,
"author" : "niko",
"class_number" : 1,
"comments" : [ ],
"copy" : false,
"created" : 1403650195222,
"current" : "",
"memorized" : 1,
"permalink" : "newtest_106677414836872",
"rem" : 257,
"student" : "niko",
"tags" : [ ],
"title" : "newtest"
}
{
"_id" : ObjectId("53aa0093e99034914b000004"),
"ans" : 1,
"author" : "niko",
"class_number" : 2,
"comments" : [ ],
"copy" : false,
"created" : 1403650195253,
"current" : "",
"memorized" : 1,
"permalink" : "newtest_91237262691445",
"rem" : 603,
"student" : "niko",
"tags" : [ ],
"title" : "newtest"
}
{
"_id" : ObjectId("53aa0093e99034914b000002"),
"ans" : 2,
"author" : "niko",
"class_number" : 0,
"comments" : [ ],
"copy" : false,
"created" : 1403650195217,
"current" : "",
"memorized" : 1,
"permalink" : "newtest_5614600780868",
"rem" : 391,
"student" : "niko",
"tags" : [ ],
"title" : "newtest"
}
{
"title" : "rockin",
"author" : "niko",
"student" : "niko",
"current" : "",
"permalink" : "rockin_44917561926464",
"tags" : [ ],
"comments" : [ ],
"created" : 1403673810202,
"memorized" : 1,
"ans" : 1,
"rem" : 1,
"copy" : false,
"class_number" : 0,
"_id" : ObjectId("53aa5cd2ff9163968f000002")
}
{
"title" : "rockin",
"author" : "niko",
"student" : "niko",
"current" : "",
"permalink" : "rockin_68780016699996",
"tags" : [ ],
"comments" : [ ],
"created" : 1403673810204,
"memorized" : 1,
"ans" : 1,
"rem" : 1,
"copy" : false,
"class_number" : 1,
"_id" : ObjectId("53aa5cd2ff9163968f000003")
}
If you are looking for matching the "student" to the "author" then your best bet for hitting this all in one go is the aggregation framework:
db.collection.aggregate([
{ "$group": {
"_id": {
"user": {
"$cond": [
{ "$eq": [ "$student", "$author" ] },
"$student",
false
]
},
"title": "$title"
}
}},
{ "$match": { "_id.user": { "$ne": false } }}
])
So the $group brings all the "distinct" combinations of "user" and "title" together while conditionally evaluating under the $cond operator whether those fields are matching or not.
The $match just filters out those distinct "titles" where the user match evaluated to false.
I have a collections
users
{
"_id" : ObjectId("53738eb7ac8ee07007c1d75a"),
"first" : "Shivam",
"connections" : [
{
"invit_made" : [ ],
"fl_no" : 615,
"date" : ISODate("2014-05-16T00:00:00Z"),
"fl" : "LB",
"TYP" : "ZLP",
"invit_reciv" : [ ],
},
{
"invit_made" : [ ],
"fl_no" : 615,
"date" : ISODate("2014-05-20T00:00:00Z"),
"fl" : "LB",
"invit_reciv" : [ ],
"TYP" : "ZLP",
}
]
}
I am performing update accoding to date in connections.but wrong nested documented is updated in my case.
db.users.update(
{ 'connections.TYP' : 'ZLP'
,'connections.fl' : 'LB'
,'connections.date' : ISODate("2014-05-20T00:00:00Z")
},
{ '$addToSet' : {
'connections.$.invit_reciv' : { 'last' : 'abc'}
}
})
Actual Result I am getting.
{
"_id" : ObjectId("53738eb7ac8ee07007c1d75a"),
"first" : "Shivam",
"connections" : [
{
"invit_made" : [ ],
"fl_no" : 615,
"date" : ISODate("2014-05-16T00:00:00Z"),
"fl" : "LB",
"TYP" : "ZLP",
"invit_reciv" : [
{
"last" : "abc"
}
],
},
{
"invit_made" : [ ],
"fl_no" : 615,
"date" : ISODate("2014-05-20T00:00:00Z"),
"fl" : "LB",
"invit_reciv" : [ ],
"TYP" : "ZLP",
}
]
}
Result I expect
{
"_id" : ObjectId("53738eb7ac8ee07007c1d75a"),
"first" : "Shivam",
"connections" : [
{
"invit_made" : [ ],
"fl_no" : 615,
"date" : ISODate("2014-05-16T00:00:00Z"),
"fl" : "LB",
"TYP" : "ZLP",
"invit_reciv" : [ ],
},
{
"invit_made" : [ ],
"fl_no" : 615,
"date" : ISODate("2014-05-20T00:00:00Z"),
"fl" : "LB",
"invit_reciv" : [
{
"last" : "abc"
}
],
"TYP" : "ZLP",
}
]
}
Please help me understand what is happening in present query and what is wrong with it.
You should use $elemMatch with positional operator, it allows you to match specific nested doc:
db.users.update(
{ connections:{
$elemMatch:{
'TYP' : 'ZLP',
'fl' : 'LB',
'date' : ISODate("2014-05-20T00:00:00Z")
}
}
},
{ '$addToSet' : {
'connections.$.invit_reciv' :
{ 'last' : 'abc'}
}
}
)