I have a mongodb collection where objects are structured as such:
{
"id": "1234",
"history": [
{
"userid": 100,
"myobjects": [{id, id1, id4}]
},
{
"userid": 200,
"myobjects": [{id2, id3, id5}]
},
}
Goal: if my userid is 100, return an object that doesn't contain my userid in its history. I'm guessing it'd be some kind of "my userid not in keys of history field" but i'm not sure how to write that out. Here's my basic idea:
Collection.findOne(
{
in_progress : null,
history : {"$nin": myuserid } ???
}
);
Any help would be appreciated!
Use MongoDB aggregation.
db.test.aggregate([
{
"$unwind" : "$history"
},
{
"$match" : {
"history.userid" : {
"$ne" : 100
}
}
},
{
"$group" : {
"_id" : "$id",
"history" : {
"$push" : "$history"
}
}
}
]);
Related
Given the following document data in collection called 'blah'...
[
{
"_id" : ObjectId("60913f55987438922d5f0db6"),
"procedureCode" : "code1",
"description" : "Description 1",
"coding" : [
{
"system" : "ABC",
"code" : "L111"
},
{
"system" : "DEFG",
"code" : "S222"
}
]
},
{
"_id" : ObjectId("60913f55987438922d5f0dbc"),
"procedureCode" : "code2",
"description" : "Description 2",
"coding" : [
{
"system" : "ABC",
"code" : "L999"
},
{
"system" : "DEFG",
"code" : "X3333"
}
]
}
]
What I want to get is all of the coding elements where system is ABC for all parents, and an array of codes like so.
[
{ "code": "L111" },
{ "code": "L999" },
]
If I use db.getCollection('blah').find({"coding.system": "ABC"}) I get the parent document with any child in the coding array of ICD.
If I use...
db.getCollection("blah")
.find({ "coding.system": "ABC" })
.projection({ "coding.code": 1 })
I do get the parent documents which have a child with a system of "ABC", but the coding for "DEFG" seems to come along for the ride too.
{
"_id" : ObjectId("60913f55987438922d5f0db6"),
"coding" : [
{
"code" : "L989"
},
{
"code" : "S102"
}
]
},
{
"_id" : ObjectId("60913f55987438922d5f0dbc"),
"coding" : [
{
"code" : "L989"
},
{
"code" : "X382"
}
]
}
I have also tried experimenting with:
db.getCollection("blah").aggregate(
{ $unwind: "$coding" },
{ $match: { "system": "ICD" } }
);
.. as per this page: mongoDB query to find the document in nested array
... but go no where fast with that approach. i.e. no records at all.
What query do I need, please, to achieve something like this..?
[
{ "code": "L111" },
{ "code": "L999" },
...
]
or even better, this..?
[
"L111",
"L999",
...
]
db.collection.aggregate([
{
$match: { "coding.system": "ABC" }
},
{
$unwind: "$coding"
},
{
$match: { "coding.system": "ABC" }
},
{
$project: { code: "$coding.code" }
}
])
mongoplayground
db.collection.aggregate([
{
$match: { "coding.system": "ABC" }
},
{
$unwind: "$coding"
},
{
$match: { "coding.system": "ABC" }
},
{
$group: {
_id: null,
coding: { $push: "$coding.code" }
}
}
])
mongoplayground
Instead of $unwind, $match you can also use $filter:
db.collection.aggregate([
{ $match: { "coding.system": "ABC" } },
{
$project: {
coding: {
$filter: {
input: "$coding",
cond: { $eq: [ "$$this.system", "ABC" ] }
}
}
}
}
])
Hello I am new to mongoDB, please I hope you can help me with this question.
My collection will look like this:
{
"_id": { "$oid": "5f1fd47..." },
"email":"c#c.com",
"materials": [
{
"_id": { "$oid": "5f1fda2..." },
"title": "MDF 18mm Blanco",
"id": "mdf18blanco",
"thickness": "18",
"family": "MDF",
"color": ""
}, ...
//others materials with different family
],
}
I did an aggregate like this:
{ "$match" : { "email" : "c#c.com" } },
{ "$unwind" : "$materials" },
{ "$group" : { "_id" : "$_id", "list" : { "$push" : "$materials.family" } } }
and I return this:
{
"_id" : ObjectId("5f1fd47d502e00051c673dd1"),
"list" : [
"MDF",
"MDF",
"MDF",
"Melamina",
"Melamina",
"Melamina",
"Melamina",
"MDF",
"Melamina",
"Aglomerado",
"Aglomerado"
]
}
but i need get this
{
"_id" : ObjectId("5f1fd47d502e00051c673dd1"),
"list" : [
"MDF",
"Melamina",
"Aglomerado"
]
}
I hope you understand my question and can help me, thank you very much.
All you need to do is use $addToSet instead of $push in your group stage:
{ "$group" : { "_id" : "$_id", "list" : { "$addToSet" : "$materials.family" } } }
One thing to note is that $addToSet does not guarantee a specific order as opposed to $push in case it matters to you.
You only need change $push to $addToSet.
A set not contains repeat values so it works.
db.collection.aggregate([
{
"$match": {
"email": "c#c.com"
}
},
{
"$unwind": "$materials"
},
{
"$group": {
"_id": "$_id",
"list": {
"$addToSet": "$materials.family"
}
}
}
])
Mongo Playground example
Basically the structure is :
{
"_id" : ObjectId("123123"),
"stores" : [
{
"messages" : [
{
"updated_time" : "2018-05-15T05:12:25+0000",
"message_count" : 4,
"thread_id" : "123",
"messages" : [
{
"message" : "Hi User ",
"created_time" : "2018-05-15T05:12:25+0000",
"message_id" : "111",
},
{
"message" : "This is tes",
"created_time" : "2018-05-15T05:12:21+0000",
"message_id" : "222",
}
]
},
],
"store_id" : "123"
}
]
}
I have these values to get message_id object : 111. So how to get this object, any idea or help will be appreciated. THanks
store_id: 123,
thread_id:123,
message_id:111
The simplest way would be to $unwind all the nested arrays and then use $match to get single document. You can also add $replaceRoot to get only nested document. Try:
db.collection.aggregate([
{ $unwind: "$stores" },
{ $unwind: "$stores.messages" },
{ $unwind: "$stores.messages.messages" },
{ $match: { "stores.store_id": "123", "stores.messages.thread_id": "123", "stores.messages.messages.message_id": "111" } },
{ $replaceRoot: { newRoot: "$stores.messages.messages" } }
])
Prints:
{
"created_time": "2018-05-15T05:12:25+0000",
"message": "Hi User ",
"message_id": "111"
}
To improve the performance you can use $match after every $unwind to filter out unnecessary data as soon as possible, try:
db.collection.aggregate([
{ $unwind: "$stores" },
{ $match: { "stores.store_id": "123" } },
{ $unwind: "$stores.messages" },
{ $match: { "stores.messages.thread_id": "123" } },
{ $unwind: "$stores.messages.messages" },
{ $match: { "stores.messages.messages.message_id": "111" } },
{ $replaceRoot: { newRoot: "$stores.messages.messages" } }
])
I am currently getting a response in mongoose like this
{
"_id" : "5a0be40836341c8ef9dc6d9d",
"Username" : "Adkins Daugherty",
"ContactDetail" : {
"ApiID" : "5a0be408ed6983954888bdb5",
"ContactName" : "Pace Roach",
}
}
But i want like this :
{
"_id" : "5a0be40836341c8ef9dc6d9d",
"Username" : "Adkins Daugherty",
"ApiID" : "5a0be408ed6983954888bdb5",
"ContactName" : "Pace Roach",
}
How can i do this using mongoose. My collection name is contacts
Thanks
EDIT-1
db.contacts.aggregate([{
$match: { Username: 'year_Adkins Daugherty' } },
{ "$unwind": "$ContactDetail" },
{
"$group": { "_id": "$_id",
"ApiID": "$ContactDetail.ApiID"
}
}
])
I think I got an answer in $project
return Contact.aggregate(
[
{ $match: { Username: regex } },
{
$project:{
Username:1,
ApiID:"$ContactDetail.ApiID",
Name:"$ContactDetail.ContactName",
ProfileImageUrl:"$ContactDetail.ProfileImageUrl",
OutletName:"$ContactDetail.OutletName"
}
}
]
).exec()
The result I got is
{
"_id": "5a0be40836341c8ef9dc6d9d",
"Username": "year_Adkins Daugherty",
"ApiID": "5a0be408ed6983954888bdb5",
"Name": "Pace Roach",
"ProfileImageUrl": "http://placehold.it/256x256",
"OutletName": "Codehow___kjvolyi3ye"
}
I have a mongodb collection with millions of records regarding transactions. I would like to create a query aggregated by date and resolution.
My document look like:
{
"_id": "Dan",
"finish_date": "2017-01-02 15:23:45.234Z",
"resolution": "canceled"
}
{
"_id": "John",
"finish_date": "2017-01-02 18:54:19.090Z",
"resolution": "completed"
}
{
"_id": "Pete",
"finish_date": "2017-01-02 19:11:27.418Z",
"order_resolution": "completed"
}
I would like the query output to look something like:
{
"2017-01-02" : {
"canceled": 1,
"completed": 2,
}
}
{
"2017-01-03" : {
"completed": 5,
}
}
Is this even possible? Currently, my output looks like:
{
"_id" : {
"curDate" : "2017-01-02",
"reason" : "canceled"
},
"count" : 1.0
}
"_id" : {
"curDate" : "2017-01-02",
"reason" : "completed"
},
"count" : 2.0
}
{
"_id" : {
"curDate" : "2017-01-03",
"reason" : "completed"
},
"count" : 5.0
}
The query looks like:
db.collection.aggregate(
[
{
"$match": {
"finish_date": {
"$gt": new Date("2017-01-02"),
"$lt": new Date("2017-01-08")
}
}
},
{
"$group" : {
_id : {
curDate: {
$substr: ["$finish_date", 0, 10]
},
reason: "$resolution"
},
count: { "$sum": 1 }
}
},
{
"$sort": { "_id.curDate": 1, "_id.reason": 1 }
}
]
)
You can use the new operator $arrayToObject available in 3.4.4 version with below aggregation query.
$group by curDate and push the reason and count values into reasoncount array.
$zip the reason and count array values together followed by $arrayToObject to create reason and count structure.
Same logic to create a curDate structure while keeping the previous reason and count structure.
db.collection.aggregate(
[
{$match:{finish_date:{$gt: new Date("2017-01-02"),$lt: new Date("2017-01-08")}}},
{$group:{_id:{curDate:{$substr:["$finish_date",0,10]},reason:"$resolution"},count:{$sum: 1}}},
{$sort:{"_id.curDate":1,"_id.reason":1}},
{$group:{_id:"$_id.curDate", reasoncount:{$push:{reason:"$_id.reason",count:"$count"}}}},
{$addFields:{reasoncount: {$arrayToObject:{$zip:{inputs:["$reasoncount.reason", "$reasoncount.count"]}}}}},
{$group:{_id:null, result:{$push:{curDate:"$_id",reasoncount:"$reasoncount"}}}},
{$addFields:{result: {$arrayToObject:{$zip:{inputs:["$result.curDate", "$result.reasoncount"]}}}}}
]
)