I have to insert an object in every array in the MongoDB document. The items array displayed below has itemList; in every itemList I have to insert a itemSpec. The desired document shape before and after the process is shown below:
Before process
{
"items": [
{
"itemList":{
"rejected": true
},
"fProcBy": "automatic"
},
{
"itemList":{
"rejected": true
},
"fProcBy": "automatic"
}
]
}
After process:
{
"items": [
{
"itemList":{
"rejected": true
},
"itemSpec":{
"approved": true
},
"fProcBy": "automatic"
},
{
"itemList":{
"rejected": true
},
"itemSpec":{
"approved": true
},
"fProcBy": "automatic"
}
]
}
So in each element of the items array there has to be inserted a new object property itemSpec.
I am not aware of a solution which does it in a single run, but with the following simple script the maximal number of iterations is equal to the maximal number of array elements you have in a single documents, which is probably not so high (but it's just a guess as I have no further information about your data):
var q = { "items.itemSpec": null };
var u = {
$set: {
"items.$.itemSpec" : {
"approved": true
}
}
};
var yourColl = db.getCollection('fooBar');
while (yourColl.find(q).count() > 0) {
yourColl.update(q, u, { multi: true });
}
Use $push operator to update array in a document.
Try This:
db.test.update({"_id":"yourUniqueId"},
{$push: { "items":{ "itemSpec":{"approved": true}}}});
Related
I want to update this document in MongoDB
[
{
"persons" : [
{
"name":"Javier",
"occupation":"teacher"
},
{
"name":"Juliana",
"occupation":"novelist"
},
{
"name":"Henry",
"occupation":"plumber"
}
]
}
]
let's say I have a global array variable that contains this
var peopleGlobalVar = [
{
"name":"Javier",
"occupation":"gardener"
},
{
"name":"Henry",
"occupation":"postman"
}
]
I want to update the document with the value in globalVar WITHOUT common javascript looping, so if the names match, the occupation value will change, and I'm looking for the "pure query" solution.
the code I expect:
collection.update(
{},
{
$set: {
// code ...
}
},
{
$arrayFilter: [
{
"elem.name": {
$in:
$function : {
body: function(updatedPeopleFromGlobalVariable){
let names = [];
updatedPeopleFromGlobalVariable.forEach(function(person){
names.push(person.name);
return names;
},
args: peopleGlobalVar,
lang:"js",
}
},
"multi": true
}
]
}
)
What the output should be
[
{
"persons" : [
{
"name":"Javier",
"occupation":"gardener"
},
{
"name":"Juliana",
"occupation":"novelist"
},
{
"name":"Henry",
"occupation":"postman"
}
]
}
]
Anyone have the solution to this?
I am trying to insert, update values in the MongoDB array.
My MongoDB version is 4.0.5.
Here is my collection :
{
'id': 1,
'array': [{
'code': 'a'
}, {
'code': 'b'
}]
}
I am trying to make some upsert queries to insert/update into an array but I don't found a good solution until then.
My filters are :
'id' (to point the correct document)
'array.code' (to point the correct array cell)
If the document exists in the collection but there is no cell with 'code': 'c'
db.test.update({
'id': 1
}, {
$set: {'array.$[elem].test':'ok'}
}, {
upsert: true,
arrayFilters: [{'elem.code': 'c'}]
}
)
I have no error but no upsert too.
I want to insert the element in the array like this :
// Desired result
{
'id': 1,
'array': [{
'code': 'a'
}, {
'code': 'b'
}, {
'code': 'c'
'test': 'ok'
}]
}
If the document doesn't exist in the collection
db.test.update({
'id': 3
}, {
$set: {'array.$[elem].test':'ok'}
}, {
upsert: true,
arrayFilters: [{'elem.code': 'a'}]
}
)
In that case, I have this error :
WriteError: The path 'array' must exist in the document in order to apply array updates., full error: {'index': 0, 'code': 2, 'errmsg': "The path 'array' must exist in the document in order to apply array updates."}
I want to upsert a new document with elements of the query like this :
// Desired result
{
'id': 3,
'array': [{
'code': 'a'
'test': 'ok'
}]
}
upsert: true in the query parameters doesn't seem to work with the array.
Your help will be highly appreciated.
The upsert is not effective in the array, If you do update MongoDB version from 4.0.5 to 4.2 then you can able to use update with aggregation pipeline starting from MongoDB 4.2,
Case 1: If the document exists in the collection but there is no cell with 'code': 'c':
var id = 2;
var item = { code: "c", test: "ok" };
Playground
Case 2: If the document doesn't exist in the collection:
var id = 3;
var item = { code: "a", test: "ok" };
Playground
$ifNull to check if the field does not exist then return empty
$cond to check if input code is in array
yes, then $mep to iterate loop of array and check condition if match then update other fields otherwise return an empty object
$mergeObjects to merge current object with updated fields
no, $concatArrays to concat current array with new item object
db.collection.update(
{ "id": id },
[{
$set: {
array: {
$cond: [
{
$in: [item.code, { $ifNull: ["$array.code", []] }]
},
{
$map: {
input: "$array",
in: {
$mergeObjects: [
"$$this",
{
$cond: [{ $eq: ["$$this.code", "c"] }, item, {}]
}
]
}
}
},
{
$concatArrays: [{ $ifNull: ["$array", []] }, [item]]
}
]
}
}
}],
{ upsert: true }
)
I am trying to find if any documents present and size more than one for a list which is inside two other lists in Mongo.
this is how my collection looks like:
{
"value": {
"items": [
{
"docs": [
{
"numbers": [
1,
2
]
},
{
"numbers": [
1
]
}
]
}
]
}
}
I tried to use this query and it did not work:
db.getCollection('MyCollection').find({"value.items.docs.numbers":{ $exists: true, $gt: {$size: 1} }})
What should be the ideal query to search if more than one item present inside list of list.
You are checking condition in nested array, for that nested $elemMatch condition will help to check conditions
$size allow only number as input so $not will help in negative condition
$ne to check array size should not [] empty
db.getCollection('MyCollection').find({
"value.items": {
$elemMatch: {
docs: {
$elemMatch: {
numbers: {
$exists: true,
$ne: [],
$not: {
$size: 1
}
}
}
}
}
}
})
Playground
I need to add a completed attribute using addField aggregate query, if the orders array inside a collection (sales) contains an object with status attribute having value delivered.
db.sales.insertMany([
{
"_id" : 1,
"salesId" : "2938432",
"customerId" : "987677789",
"amount:"23000"
"orders":[{
orderId:"TX8383428979382",
status:"cancelled"
},
{
orderId:"TX8383428979383",
status:"fullfilled"
}]
},
{
"_id" : 1,
"salesId" : "2938433",
"customerId" : "987676578",
"amount:"13000"
"orders":[
{
orderId:"TX838342892437363",
status:"placed"
}]
},
.........
)]
My aggregate query
db.sales.aggregate([
{$match:{....}},
{$addFields:{
completed: {
$cond: { if: { /* code to check if orders array contains an object with `status:fullfilled` }, then: true, else: false }
}
}},
])
How can I check for a match for an attribute inside array of objects.?
Here is the aggregation which uses the $reduce array operator to add a new attribute completed which is derived based upon the orders.status "delivered".
db.sales.aggregate( [
{
$addFields: {
completed: {
$reduce: {
input: "$orders", initialValue: false,
in: {
$cond: [ { $eq: [ "$$this.status", "delivered" ] },
true,
"$$value"
]
}
}
}
}
}
] ).pretty()
This is the document I currently have:
{
"_id": "",
"title": "My Watchlist",
"series": [{
"seriesId": 1,
"following": true,
"seasons": []
}, {
"seriesId": 1,
"following": false,
"seasons": []
}]
}
As you can see there are currently 2 objects with the seriesId 1, but with a different following boolean.
If the query matches with _id it should push the new object into series, if within the "series"-array an object with the same "seriesId" already exists it should change the fields within that object, instead of adding a new object.
I currently have the following query:
users.update(
{"_id": req.body.userId},
{
"$push": {
"series": {"seriesId": req.body.seriesId, "following": req.body.following}
}
}, (err, data) => {
if (err)
next(err);
});
If I use $set it does not add the object if it didn't originaly exist yet, and as far as I know you cannot both use $push and $set?
Can this be fixed in any way or do I have to rethink my Schema?
You can use two update query :
if _id is found and seriesId is not in the array, add the new item to the array :
db.series.update({
"_id": req.body.userId,
"series": {
"$not": {
"$elemMatch": {
"seriesId": req.body.seriesId
}
}
}
}, {
$addToSet: {
series: {
"seriesId": req.body.seriesId,
"following": req.body.following,
"seasons": []
}
}
}, { multi: true });
if _id is found and seriesId is found in the array, update the array item :
db.series.update({
"_id": req.body.userId,
"series.seriesId": req.body.seriesId
}, {
$set: {
"series.$.following": req.body.following
}
}, { multi: true });