Update in forEach on mongodb shell

后端 未结 3 1244
天命终不由人
天命终不由人 2020-12-14 16:12

I have got a collection aTable with 2 records:

 {
    \"title\" : \"record 1\",
    \"fields\" : [ 
        {
            \"_id\" : 1,
              


        
相关标签:
3条回答
  • 2020-12-14 16:42

    To get what you want you will need a few things:

    t.forEach(function( aRow ) {
        var newFields = [];
        aRow.fields.forEach( function( aField ){
            var newItems = [];
            aField.items.forEach( function( item ){
                var aNewItem = { item: parseInt(item), ref: 0 };
                newItems.push( aNewItem );
            } );
            newFields.push({ _id: aField._id, items: newItems });
        } )
        aTable.update(
            { _id: aRow._id }, 
            { "$set": { "fields": newFields } }
        );
    });
    

    So basically you need to "re-construct" your arrays before updating

    0 讨论(0)
  • 2020-12-14 16:52

    You can make changes directly in the whole object and then save it. Try the following snippet

    db.aTable.find().forEach(function (itemWrapper){
        itemWrapper.fields.forEach(function(field){
            var items = field.items;
            var newItems = [];
            items.forEach(function(item){
              var t = {'item':item,'key':0}
              newItems.push(t);      
            })
            field.items = newItems;
        })
        db.aTable.save(itemWrapper)
    })
    

    What I am doing is iterating over all items and making a new array with {item : 1 , key:0} and then setting it back to items array in field object.

    This is the output after update :

    {
        "_id" : ObjectId("5332a192ece4ce8362c7a553"),
        "title" : "record 1",
        "fields" : [ 
            {
                "_id" : 1,
                "items" : [ 
                    {
                        "item" : 1,
                        "key" : 0
                    }
                ]
            }, 
            {
                "_id" : 2,
                "items" : [ 
                    {
                        "item" : 2,
                        "key" : 0
                    }, 
                    {
                        "item" : 3,
                        "key" : 0
                    }, 
                    {
                        "item" : 4,
                        "key" : 0
                    }
                ]
            }, 
            {
                "_id" : 3,
                "items" : [ 
                    {
                        "item" : 5,
                        "key" : 0
                    }
                ]
            }
        ]
    }
    
    /* 1 */
    {
        "_id" : ObjectId("5332a192ece4ce8362c7a554"),
        "title" : "record 2",
        "fields" : [ 
            {
                "_id" : 4,
                "items" : [ 
                    {
                        "item" : 7,
                        "key" : 0
                    }, 
                    {
                        "item" : 8,
                        "key" : 0
                    }, 
                    {
                        "item" : 9,
                        "key" : 0
                    }, 
                    {
                        "item" : 10,
                        "key" : 0
                    }
                ]
            }, 
            {
                "_id" : 5,
                "items" : []
            }, 
            {
                "_id" : 6,
                "items" : [ 
                    {
                        "item" : 11,
                        "key" : 0
                    }, 
                    {
                        "item" : 12,
                        "key" : 0
                    }
                ]
            }
        ]
    }
    
    0 讨论(0)
  • 2020-12-14 17:02

    Starting Mongo 4.2, db.collection.update() can accept an aggregation pipeline, finally allowing the update of a field based on its current value, and thus using a query instead of javascript:

    // {
    //   title: "record 1",
    //   fields: [
    //     { _id: 1, items: [1] },
    //     { _id: 2, items: [2, 3, 4] },
    //     { _id: 3, items: [5] }
    //   ]
    // }
    db.collection.update(
      {},
      [{ $set: {
           fields: { $map: {
             input: "$fields",
             as: "x",
             in: {
               _id: "$$x._id",
               items: { $map: {
                 input: "$$x.items",
                 as: "y",
                 in: { item: "$$y", key: 0 }
               }}
             }
           }}
      }}],
      { multi: true }
    )
    // {
    //   title: "record 1",
    //   fields: [
    //     { _id: 1, items: [ { item: 1, key: 0 } ] },
    //     { _id: 2, items: [ { item: 2, key: 0 }, { item: 3, key: 0 }, { item: 4, key: 0 } ] },
    //     { _id: 3, items: [ { item: 5, key: 0 } ] }
    //   ]
    // }
    
    • The first part {} is the match query, filtering which documents to update (in this case all documents).

    • The second part [{ $set: { fields: { $map: { ... } } }] is the update aggregation pipeline (note the squared brackets signifying the use of an aggregation pipeline):

      • $set is a new aggregation operator which in this case replaces the field's value.
      • Then (if we go passed the boilerplate) we're simply $mapping the two nested arrays.
      • More specifically, the second map transformation replaces [1, 2] by [{ item: 1, key: 0 }, { item: 2, key: 0 }].
    • Don't forget { multi: true }, otherwise only the first matching document will be updated.
    0 讨论(0)
提交回复
热议问题