5

I have the following schema. I am using node.js with mongodb

attributes: {
    type: { type: 'string' },
    title: { type:'string' },
    description: { type:'string' },
    is_active: { type:'boolean',defaultsTo:true },
    createdBy: { type:'json' },
    attachments:{ type:'array' }
}

arr = [{
    'id':attResult.id,
    'subtype':type,
    'title'  : attResult.title,
    'body'  : attResult.body,
    'filetype' : attResult.filetype
}];

I am trying to push a attachments into the 'attachments' array that will be unique to the document.

This is the my query.

books.update(
    { id: refid },
    { $push: { attachments: arr } }
).done(function (err, updElem) {
    console.log("updElem" + JSON.stringify(updElem));     
});

What is the problem in my query,no error but not updated attachments.

I want my result to be this:

{ 
    "_id" : 5,
    "attachments": [
        { 
            "id": "xxxxxxx",
            "subtype": "book",
            "title": "xxxx",
            "body": "xxxx" ,
            "filetype" : "xxxxx"
        },
        {
            "id": "xxxxxxx",
            "subtype": "book",
            "title": "xxxx",
            "body": "xxxx",
            "filetype": "xxxxx"
        }
    ]
}
2
  • What are you really using here? Mongoose perhaps? Do you mean "attributes" to be your schema definition? Or is the definition actually additional fields under a field called "attributes"? Commented Jun 7, 2014 at 7:34
  • You're trying to push an array, try pushing one item instead or using a combination of $each with $push. check here Commented Dec 14, 2023 at 13:41

3 Answers 3

10

Someone who trying to push the element into an array is possible now, using the native mongodb library.

Considering the following mongodb collection object

{ 
"_id" : 5,
"attachments": [
    { 
        "id": "xxxxxxx",
        "subtype": "book",
        "title": "xxxx",
        "body": "xxxx" ,
        "filetype" : "xxxxx"
    },
    {
        "id": "xxxxxxx",
        "subtype": "book",
        "title": "xxxx",
        "body": "xxxx",
        "filetype": "xxxxx"
    }
]
}


 arr = [{
 'id':'123456',
 'subtype':'book',
 'title'  : 'c programing',
 'body'  :' complete tutorial for c',
 'filetype' : '.pdf'
 },
{
 'id':'123457',
 'subtype':'book',
 'title'  : 'Java programing',
 'body'  :' complete tutorial for Java',
 'filetype' : '.pdf'
 }
];

The following query can be used to push the array element to "attachments" at the end. $push or $addToSet can be used for this.

This will be inserting one object or element into attachments

db.collection('books').updateOne(
  { "_id": refid }, // query matching , refId should be "ObjectId" type
  { $push: { "attachments": arr[0] } } //single object will be pushed to attachemnts
 ).done(function (err, updElem) {
  console.log("updElem" + JSON.stringify(updElem));     
});

This will be inserting each object in the array into attachments

   db.collection('books').updateOne(
     { "_id": refid }, // query matching , refId should be "ObjectId" type
     { $push: { "attachments":{$each: arr} } } // arr will be array of objects
     ).done(function (err, updElem) {
           console.log("updElem" + JSON.stringify(updElem));     
    });
Sign up to request clarification or add additional context in comments.

1 Comment

add a bit of explanation to support your answer Ashokan
3

Looking at your question a little bit more I'm betting that you are actually using "sails" here even though your question is not tagged as such.

The issue here is that the waterline ODM/ORM has it's own ideas about what sort of operations are actually supported since it tries to be agnostic between working with SQL/NoSQL backends and sort of demands a certain may of doing things.

The result is that updates with $push are not really supported at present and you need more of a JavaScript manipulation affair. So in fact you need to manipulate this via a .findOne and .save() operation:

books.findOne(refid).exec(function(err,book) {
   book.attachments.push( arr[0] );
   book.save(function(err){
     // something here
   });
});

Part of that is "waterline" shorthand for what would otherwise be considered an interchangeable use of _id and id as terms, where just specifying the id value as a single argument implies that you are referring to the id value in your query selection.

So unless you replace the waterline ODM/ORM you are pretty much stuck with this AFAIK until there is a decision to maintain this logic in a way that is more consistent with the MongoDB API or otherwise allow access to the "raw" driver interface to perform these .update() operations.

For reference though, and has been alluded to, your general "shell" syntax or what would otherwise be supported in MongoDB specific drivers is like this with the deprecation of the $pushAll operator and the intention being to merge the functionality with the $push and $addToSet operators using the $each modifier:

db.collection.update(
   { "_id": ObjectId(refid) },    // should be important to "cast"
   {
      "$push": {
          "attachments": {
              "$each": arr
          }
      }
   }
)

So that syntax would work where it applies, but for you I am thinking that in "sails" it will not.

That gives you some food for thought, and some insight into the correct way to do things.

2 Comments

Hai thanks to all.i tried "_id" method.thats one also same problem.but i tried mongodb save method working .Thanks to all.
@user3046205 So you are using sails? I pretty much explained why that is the only way this works with sails is by retrieving the data then manipulating and then using .save(). It does help if you confirm this so we can re-classify your question as well as accepting the answer let's people know there was a solution.
1

You are trying to insert an array as an element into your array. You may want to look at $pushAll as a short term solution. This operator is deprecated however see here.

Alternatively you can simply iterate over your array, and each iteration push an element from your array into attachments (this is the recommended approach by Mongo devs).

1 Comment

Hi martin, i tried $pullAll still same problem. please help me how can i fix this issue.Tnks

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.