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})
Related
I need help with following thing in MongoDB, what I'm trying to do is to get only marks in reviews into it's own array of values only.
Code i got so far:
db.lodging.aggregate([
{$project:{
reviews:"$host.reviews",host:"$host"
}
},
{$unwind: "$reviews"},
])
JSON Example:
"host" : {
"name" : "Grimes",
"surname" : "Terrell",
"gender" : "male",
"age" : NumberInt(55),
"picture" : "https://api.adorable.io/avatars/285/GrimesTerrell.png",
"reviews" : [
{
"reviewer" : "Mae Ryan",
"date" : "2015-06-01T02:41:46 -02:00",
"helpful" : NumberInt(8),
"kind" : NumberInt(1),
"responsive" : NumberInt(5)
},
{
"reviewer" : "Nixon Johnson",
"date" : "2016-02-08T10:35:12 -01:00",
"helpful" : NumberInt(1),
"kind" : NumberInt(1),
"responsive" : NumberInt(9)
},
]
}
This is what im trying to achieve:
{
"host" : {
"name" : "Grimes",
"surname" : "Terrell",
"gender" : "male",
"age" : NumberInt(55),
"picture" : "https://api.adorable.io/avatars/285/GrimesTerrell.png",
"reviews" : [
{
"marks" : [8,1,5],
},
{
"marks" : [1,1,9],
},
]
}
Assuming your marks' field names are always helpful, kind, responsive, you can use $map.
Here is a mongo playground for you reference
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 })
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")})
I have to update an Array nested in another Array.
Is it possible to do that with the $addtoset operator?
Here is my document.
I have a library wich has an Array of authors who have an Array of Books.
In this exemple, i'd like to add a new category to the book id 1 of the author id 1
How can i do that ?
{
"id" : NumberLong(666),
"library" : [
{
"id" : NumberLong(8888),
"author" : [
{
"id" : NumberLong(1),
"books" : [
{
"id":1,
"title" : "plop",
"category" : ["horror"],
"isbn" : 12345
},
{
"id":2,
"title" : "plup",
"category" : ["comics"],
"isbn" : 6789
}
]
},
{
"id" : NumberLong(2),
"books" : [
{
"id":3,
"title" : "blop",
"category" : ["horror"],
"isbn" : 96325
},
{
"id":4,
"title" : "blup",
"category" : ["comics"],
"isbn" : 74125
}
]
}
]
}
]
}
I tried this :
db.library.update(
{"id":666,"author.id":1,"books.id":1},
{"$addToSet": {"author.$.books.category": "humour" }}
)
But it doesn't works
How does it works ?
thanks a lot
db.library.update(
{"id":666,"library.author.id":1,"library.author.books.id":1},
{"$addToSet": {"library.0.author.0.books.$.category": "Book"}}
)