[
{
"_id" : ObjectId("5abce64d86d3289de052a639"),
"username" : "doggy",
"email" : "doggy#sabanciuniv.edu",
"password" : "iLoveDoggy",
"friends" : [
{
"username" : "djBackend",
"status" : "2"
},
{
"username" : "eggroid",
"status" : "1"
},
{
"username" : "Berk",
"status" : "2"
}
]
},
{
"_id" : ObjectId("5ab90f25e7708f0f4455075a"),
"username" : "guiBOI",
"email" : "iDoGUI#sabanciuniv.edı",
"password" : "animeKeyfisi",
"friends" : [
{
"username" : "djBackend",
"status" : "2"
},
{
"username" : "eggroid",
"status" : "1"
}
]
}
]
I have the format of JSON as storage in my mongoDB. What i would like to do is that find the username with "doggy" which is
{
"_id" : ObjectId("5abce64d86d3289de052a639"),
"username" : "doggy",
"email" : "doggy#sabanciuniv.edu",
"password" : "iLoveDoggy",
"friends" : [
{
"username" : "djBackend",
"status" : "2"
},
{
"username" : "eggroid",
"status" : "1"
},
{
"username" : "Berk",
"status" : "2"
}
]
}
and change its status of username named as "eggroid" "1" to "2". I have been trying it with db.collection.findAndModify(document); but no success, i am new to mongoDB so sorry if this is a newbie question but i have been struggling ober 3 hours.
You can use $ (positional operator)
db.collection.update({username: "doggy", "friends.username" : "eggroid"}, { $set: { "friends.$.status": 2} })
Based on your filtering conditions (first parameter) MongoDB will figure out which item of nested array you want to update (works only for first matched subdocument)
Related
I have some dummy data in my database. I'm trying to perform mongodb aggregation functions in order to sort based on a given title
{ "_id" : 1, "item" : "ABC1", "fields" : [ { "title" : "firstName", "value" : "Trish" }, { "title" : "zipcode", "value" : "01001" } ] }
{ "_id" : 2, "item" : "ABC2", "fields" : [ { "title" : "firstName", "value" : "Peter" }, { "title" : "zipcode", "value" : "00011" } ] }
The query that i'm able to come up with so far is this and the following is what mongodb returns.
db.test.aggregate([ {$unwind: "$fields"}, {$match: {"fields.title" : "firstName"}}, {$sort: {"fields.value" : 1} }])
{ "_id" : 2, "item" : "ABC2", "fields" : { "title" : "firstName", "value" : "Peter" } }
{ "_id" : 1, "item" : "ABC1", "fields" : { "title" : "firstName", "value" : "Trish" } }
However the result I would the returned dataset should include the other object in the fields list like so. The main thing that I am trying to accomplish is being able to sort the documents based on a specific field title
{ "_id" : 2, "item" : "ABC2", "fields" : [ { "title" : "firstName", "value" : "Peter" }, { "title" : "zipcode", "value" : "00011" } ] }
{ "_id" : 1, "item" : "ABC1", "fields" : [ { "title" : "firstName", "value" : "Trish" }, { "title" : "zipcode", "value" : "01001" } ] }
If you can guarantee the position of the fields, firstName always the first, and so on. You can sort by that. like this:
db.test.find().sort({'fields.0.value': -1})
//or
db.test.find().sort({'fields.0.value': 1})
I need to remove all the objects within array who meet the conditions i will show down below. I'll let here the documents and an example of what i've done.
//document 1
{
"_id" : ObjectId("5ec73abebd7e4d618a057350"),
"code" : "X20",
"title" : "Full stack developer",
"location" : "Paris",
"date" : ISODate("2020-05-22T02:36:46.272Z"),
"candidates" : [
{
"name" : "David",
"last_name" : "Broncano",
"telephone" : "642025552",
"email" : "david#gmail.com"
},
{
"name" : "Pablo",
"last_name" : "Claros",
"telephone" : "628721784",
"email" : "pablo#gmail.com"
}
]
}
// document 2
{
"_id" : ObjectId("4ec73abebd7e4d618a057350"),
"code" : "X50",
"title" : "Full stack developer",
"location" : "Madrid",
"date" : ISODate("2020-05-22T02:36:46.272Z"),
"candidates" : [
{
"name" : "Maria",
"last_name" : "Mars",
"telephone" : "642024582",
"email" : "dasd#gmail.com"
},
{
"name" : "Pablo",
"last_name" : "Claros",
"telephone" : "628721784",
"email" : "pablo#gmail.com"
}
]
}
So i need to remove all the candidates where location is Madrid.I have done this but it removes the field. Is it possible to just remove the content of it using $pull or something?
db.offers.update(
{ location : "Madrid"},
{
$unset:{
"candidates":""
} } ,
{
multi : true
}
)
According to my understanding, you need to just clear the candidates array and maintain that as candidates: []. For this, you can use use $set operator to set candidates to [] based on your condition
db.offers.update({ location : "Madrid"}, { $set:{ "candidates": [] } } , { multi : true })
how can I query to get the specific message from either inbox or outbox given that I have its _id --> i.e. message id.
this is my route
get("/getSpecificMessage/{Message_id}", (req, res) => {..}
what I can do is find all the buyer/dealer and then go through inbox/outbox of all the buyer/dealer and then find the message with _id i.e. message_id
--> can I do it better then that.
{
"_id" : ObjectId("5b8f0f4de276dd1e0ff083e1"),
"address" : {
"proper_address" : "sarai kale khan",
"lat" : 28.58894,
"long" : "77.25692"
},
"name" : "prashant",
"password" : "jfalksdjlk;jasdl",
"email" : "prashant#gmail.com",
"inbox" : [
{
"_id" : ObjectId("5b8f0f4de276dd1e0ff083e4"),
"date" : ISODate("2018-09-04T23:03:41.627Z"),
"from" : "1#1.com",
"message" : "message_1"
},
{
"_id" : ObjectId("5b8f0f4de276dd1e0ff083e3"),
"date" : ISODate("2018-09-04T23:03:41.627Z"),
"from" : "2#2.com",
"message" : "message_2"
},
{
"_id" : ObjectId("5b8f0f4de276dd1e0ff083e2"),
"date" : ISODate("2018-09-04T23:03:41.627Z"),
"from" : "3#3.com",
"message" : "message_3"
}
],
"outbox" : [
{
"_id" : ObjectId("5b8f0f4de276dd1e0ff083e7"),
"date" : ISODate("2018-09-04T23:03:41.627Z"),
"to" : "1#1.com",
"message" : "message_4"
},
{
"_id" : ObjectId("5b8f0f4de276dd1e0ff083e6"),
"date" : ISODate("2018-09-04T23:03:41.627Z"),
"to" : "1#1.com",
"message" : "message_5"
},
{
"_id" : ObjectId("5b8f0f4de276dd1e0ff083e5"),
"date" : ISODate("2018-09-04T23:03:41.627Z"),
"to" : "1#1.com",
"message" : "message_6"
}
],
"__v" : 0
}
{
"_id" : ObjectId("5b8f0f4de276dd1e0ff083e8"),
"address" : {
"proper_address" : "najafgarah",
"lat" : 28.58894,
"long" : "77.25692"
},
"name" : "rahul",
"password" : "jkalsjdflasdl",
"email" : "rahul#gmail.com",
"inbox" : [
{
"_id" : ObjectId("5b8f0f4de276dd1e0ff083eb"),
"date" : ISODate("2018-09-04T23:03:41.639Z"),
"from" : "1#1.com",
"message" : "message_1"
},
{
"_id" : ObjectId("5b8f0f4de276dd1e0ff083ea"),
"date" : ISODate("2018-09-04T23:03:41.639Z"),
"from" : "2#2.com",
"message" : "message_2"
},
{
"_id" : ObjectId("5b8f0f4de276dd1e0ff083e9"),
"date" : ISODate("2018-09-04T23:03:41.639Z"),
"from" : "3#3.com",
"message" : "message_3"
}
],
"outbox" : [
{
"_id" : ObjectId("5b8f0f4de276dd1e0ff083ee"),
"date" : ISODate("2018-09-04T23:03:41.639Z"),
"to" : "1#1.com",
"message" : "message_4"
},
{
"_id" : ObjectId("5b8f0f4de276dd1e0ff083ed"),
"date" : ISODate("2018-09-04T23:03:41.639Z"),
"to" : "1#1.com",
"message" : "message_5"
},
{
"_id" : ObjectId("5b8f0f4de276dd1e0ff083ec"),
"date" : ISODate("2018-09-04T23:03:41.639Z"),
"to" : "1#1.com",
"message" : "message_6"
}
],
"__v" : 0
}
So if I have the _id = 5b8f0f4de276dd1e0ff083ea and I want
{
"_id" : ObjectId("5b8f0f4de276dd1e0ff083ea"),
"date" : ISODate("2018-09-04T23:03:41.639Z"),
"from" : "2#2.com",
"message" : "message_2"
}
I am not sure if you want it using MongoDB scripts or your app language (Nodejs if I am mistaken)
This is how it works on Mongo Shell Script
db.MODEL.find( { _id: DOCUMENT_ID },
{ inbox: { $elemMatch: { _id: MESSAGE_ID } } } )
Documentation is here
If this is not what you want, please update your post and add which language/framework you are using
This is what you could do using the aggregation framework:
var oId = new ObjectId("5b8f0f4de276dd1e0ff083ea");
db.collection.aggregate({
$match: { // can be skipped but I'd personally keep it because this will use an index on "input._id"/"output._id" (if there is one) to filter out irrelevant documents
$or: [
{ "inbox": { $elemMatch: { "_id": oId } } },
{ "outbox": { $elemMatch: { "_id": oId } } },
]
}
}, {
$project: {
result: {
$concatArrays: [
{ $filter: { "input": "$inbox", "cond": { $eq: [ "$$this._id", oId ] } } },
{ $filter: { "input": "$outbox", "cond": { $eq: [ "$$this._id", oId ] } } }
]
}
}
}, {
$unwind: "$result" // flatten the result array
}, {
$replaceRoot: {
"newRoot": "$result" // move "result" contents all the way up
}
})
I have a query below that extracts a couple of values from a large nested document. It tells me the user id and the first item name for each order.
This works fine, however I want it to only return the record where the first item's name is not null and is not blank. I can't figure out how to add a second query to the $match operator below to achieve this
db.getCollection('Orders').aggregate
([
{ $match : { "Items.1" : { $exists : true }}, ???},
{ $project: {
_id:0,
'UserId': '$User.EntityId',
'ItemName': {$arrayElemAt: ['$Items.Details.ItemName', 0]}
}
}
]);
Edited to show sample document
{
"_id" : "order-666156",
"State" : "ValidationFailed",
"LastUpdated" : {
"DateTime" : ISODate("2017-09-26T08:54:16.241Z"),
"Ticks" : NumberLong(636420128562417375)
},
"SourceOrderId" : "666156",
"User" : {
"EntityId" : NumberLong(34450),
"Name" : "Bill Baker",
"Country" : "United States",
"Region" : "North America",
"CountryISOCode" : "US",
},
"Region" : null,
"Currency" : null,
"Items" : [
{
"ClientOrderId" : "18740113",
"OrigClientOrderId" : "18740113",
"Quantity" : NumberDecimal("7487.0"),
"TransactDateTime" : {
"DateTime" : Date(-62135596800000),
"Ticks" : NumberLong(0)
},
"Text" : null,
"LocateRequired" : false,
"Details" : {
"ItemName" : "Test Item 1",
"ItemCost" : 1495.20
}
},
{
"ClientOrderId" : "18740116",
"OrigClientOrderId" : "18740116",
"Quantity" : NumberDecimal("241.0"),
"TransactDateTime" : {
"DateTime" : Date(-62135596800000),
"Ticks" : NumberLong(0)
},
"Text" : null,
"LocateRequired" : false,
"Details" : {
"ItemName" : "Test Item 2",
"ItemCost" : 2152.64
}
}
]
}
You need to add the two conditions to your existing $match (not null and not blank) to check the Items as:
$match : { "Items.1" : { $exists : true, "$ne": null,"$ne":""}
If you want to check the element Items[0].Details.ItemName you can doing using the operator $and
{ $match : {
$and: [
{"Items.1" : { $exists : true }},
{"Items.Details.ItemName" : { $ne : null}},
{"Items.Details.ItemName" : { $ne : ""}},
]
}},
I have this document in stored in my collection:
{ "_id" : ObjectId("5707b95b8415b224a48a0b2d"),
"companyId" : ObjectId("570269639caabe24e4e4043e"),
"descriptions" : [
{ "id" : ObjectId("5707b95b8415b224a48a0b2a"), "description" : "test" },
{ "id" : ObjectId("570cd8164fff3a20f88c0dc9"), "description" : "test1" },
{ "id" : ObjectId("570ce6ba4fff3a052c8c570f"), "description" : "etr" },
{ "id" : ObjectId("570cf1b64fff3a1a14d71716"), "description" : "43" },
{ "id" : ObjectId("570cf1b64fff3a1a14d71717"), "description" : "43" },
{ "id" : ObjectId("570cf1b64fff3a1a14d71719"), "description" : "345" }
],
"options" : [
{ "descriptionId" : ObjectId("5707b95b8415b224a48a0b2a"), "description" : "test" },
{ "descriptionId" : ObjectId("5707b95b8415b224a48a0b2a"), "description" : "test1" }
]
}
Now I'm trying to get the objects from the options array that are matching the descriptionId and here is how I'm doing it
db.CustomFields.find({companyId: ObjectId("570269639caabe24e4e4043e")},{"options.descriptionId": ObjectId("5707b95b8415b224a48a0b2a")})
But the result contains only the descriptionId - the description property is missing.
here is how the result looks like:
{ "_id" : ObjectId("5707b95b8415b224a48a0b2d"),
"options" : [
{ "descriptionId" : ObjectId("5707b95b8415b224a48a0b2a") },
{ "descriptionId" : ObjectId("5707b95b8415b224a48a0b2a") }
]
}
Why my query is not returning the full document from the array, but only a part of it? Can you give me a push?
EDIT
This is what I'm expecting to get from the query
{ "_id" : ObjectId("5707b95b8415b224a48a0b2d"),
"options" : [
{ "descriptionId" : ObjectId("5707b95b8415b224a48a0b2a", "description" : "test") },
{ "descriptionId" : ObjectId("5707b95b8415b224a48a0b2a", "description" : "test1") }
]
}
You need to include the other query with "options.descriptionId" together with the companyId query and use projection to return just the array you want.
The following shows this:
db.customFields.find(
{
"companyId": ObjectId("570269639caabe24e4e4043e"),
"options.descriptionId": ObjectId("5707b95b8415b224a48a0b2a")
},
{ "options": 1 }
);
Output
{
"_id" : ObjectId("5707b95b8415b224a48a0b2d"),
"options" : [
{
"descriptionId" : ObjectId("5707b95b8415b224a48a0b2a"),
"description" : "test"
},
{
"descriptionId" : ObjectId("5707b95b8415b224a48a0b2a"),
"description" : "test1"
}
]
}
Try this
db.CustomFields.find({companyId: ObjectId("570269639caabe24e4e4043e"),"options.descriptionId": ObjectId("5707b95b8415b224a48a0b2a")})