1

I have a collection with document like this:

{
    "_id" : "ABC",
    "Name" : "Rajesh",
    "createstmp" : ISODate("2015-06-22T17:09:16.705Z"),
    "updstmp" : ISODate("2015-06-22T19:31:53.527Z"),
    "AvgValue" : "65",
    "PreValues" : [ 
        {
            "Date" : 20150709,
            "Rate" : [ 
                {
                    "Time" : 1566,
                    "value" : 60
                }, 
                {
                    "Time" : 1500,
                    "value" : 400
                }, 
                {
                    "Time" : 1400,
                    "value" : 100
                }, 
                {
                    "Time" : 1500,
                    "value" : 103
                }
            ]
        }
    ]
}

I want to remove the duplicate doc for a particular Date value eg If Time value is 1500, I need to pull the document and push it the new value for (Value) in single bulk operation.

Here is my query

bulk.find({ "_id":"ABC" })
    .update(
        { 
            "_id": "ABC",
            "PreValues": { "Date": 20150709 }
        },
       { 
           $pu‌​ll: { "PreValues": { "Rate": { "Time": 1000 } } }
       }
    ); 
bulk.find({ "_id":"ABC" })
    .update(
        { "_id": "ABC","PreValues": { "Date": 20150709 }},
        { $pu‌​sh : { 
            "PreValues": { "Rate": { "Time": 1000,"Rating": 100 }}
        }}
    ); 
bulk.execute();
0

1 Answer 1

1

It's not a great idea to have nested arrays since the only thing you will ever be able to do atomically is $push or $pull. See the positional $ operator for details on why "nested arrays" are not good here, but basically you can only ever match the position of the "outer" array element.

And that is basically what you are missing here, and of course the proper "dot notation" for accessing the elements:

var bulk = db.ABA.initializeOrderedBulkOp();
bulk.find({ "_id": "ABC", "PreValues.Date": 20150709 })
    .updateOne({ "$pull": { "PreValues.$.Rate": { "Time": 1500 } } })
bulk.find({ "_id": "ABC", "PreValues.Date": 20150709 })
    .updateOne({ "$push": { "PreValues.$.Rate": { "Time": 1500, "Rating": 100 } } })
bulk.execute();

Which alters the document like so:

{
    "_id" : "ABC",
    "Name" : "Rajesh",
    "createstmp" : ISODate("2015-06-22T17:09:16.705Z"),
    "updstmp" : ISODate("2015-06-22T19:31:53.527Z"),
    "AvgValue" : "65",
    "PreValues" : [
            {
                    "Date" : 20150709,
                    "Rate" : [
                            {
                                    "Time" : 1566,
                                    "value" : 60
                            },
                            {
                                    "Time" : 1400,
                                    "value" : 100
                            },
                            {
                                    "Time" : 1500,
                                    "Rating" : 100
                            }
                    ]
            }
    ]
}

That is the correct syntax for both statements there and sends both requests to the server at the same time with a single response.

Note that you need to inclide in the .find() query a field from the outer array to match. This is so the positional $ operator is populated with the matched index of that element and the operator knows which array element to act upon.

Sign up to request clarification or add additional context in comments.

4 Comments

@VinaySawant Please do not post code listings in comments. Basically you need to use the code as I have supplied it with the correct values appropriate to the document and elements you want to match. The lesson here is 1. Correct syntax for bulk operations, 2. Matching the element of the array you want to update correctly in the query conditions. 3. Usage of "dot notation" and the positional operator in updates
@VinaySawant I Just ran everything through the shell and posted the commands back here in case their were any typing mistakes. Also added how this modifies the sample you provided in your question. As you can see the result that the other values matching the "1500" amount are gone and only the new array element is added now to the array.
@VinaySawant of course it works. I just told you the code is cut/pase along with your data sample and it produces the result as shown. If it is not working for you then you are doing something different to the example here. Put your own example data into a test collection and copy and paste the code I have here ( without indentation since the shell does not like it ) and see for yourself. Also. Not a "man" and you shouldn't be making those assumptions either.
Thanks a ton friend,i appreciate your time and efforts.

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.