Mongo matching only where first element of array has certain field value - arrays

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 : ""}},
]
}},

Related

MongoDb sort on list of objects

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})

Remove objects within array in MongoDB

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 })

Problems with JSON

I'm trying to Order in ascending order the requirements that are not between 25,000 and 30,000. The requirements are information of an array which is inside of a document and the condition is that they can't be in that determined range. I'm trying to do it properly but i can't find any information about this.
Document structure
{
"_id" : ObjectId("5ec73abebd7e4d618a05734e"),
"code" : "A47",
"title" : "Software engineer",
"description" : "Analyze, design, create, test computer and software systems.",
"city" : "Madrid",
"date" : ISODate("2020-05-22T02:36:46.271Z"),
"salary" : 30000.0,
"active" : true,
"requirements" : [
"python",
"java",
"html5",
"C++",
"C#"
],
"info_company" : {
"cif" : "A00000000",
"name" : "FUTURE S.A",
"location" : "Madrid",
"web" : "www.future.es",
"about" : "We are a leading company in new technologies."
},
"pyme" : true
}
db.offers.update(
{ $ne : [ salary: {
$gte : 25000,
$lte : 35000 ]
} },
{
$push : {
requirements: {
$each : [] ,
$sort : 1
}
}
}
,
{
multi : true
} )

Found $id field without a $ref before it, which is invalid

I have this kind of documents in my mongodb (3.4):
{
"_id" : ObjectId("588e7a5951fa0982213c8f72"),
"content" : "This is example"
"createdBy" : ObjectId("5867822e10031569325c87b4"),
"title" : "Notifications",
"community" : NumberLong(7),
"updatedAt" : ISODate("2018-10-18T22:10:37.795Z"),
"tags" : [
null,
{
"type" : "question",
"$ref" : "tag",
"$id" : ObjectId("588e7a5951fa0982213c8f73"),
"$db" : "forum"
},
{
"$id" : ObjectId("588e7a5951fa0982213c8f74"),
"$db" : "forum",
"type" : "question",
"$ref" : "tag"
}
],
"status" : "opened",
"pinned" : false
}
I want to remove null from tags array, so I tried this query:
db.getCollection('question').update(
{ _id : ObjectId("588e7a5951fa0982213c8f72") },
{ $pullAll: { tags: [null] } },
{ multi: true }
)
But, I got this error:
Found $id field without a $ref before it, which is invalid.
[Edit]
I found that $id and $ref is out of sequence in the third record of the tags field. So, can I fix the sequence and remove null using update query?

Why I can't get the full document form array?

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")})

Resources