2

The contents of my collection are in this form,

{ "_id" : ObjectId("50535036381ef82c08000002"),"source_references" : [
    {
            "_id" : ObjectId("50535036381ef82c08000001"),
            "name" : "abc",
            "key" : "123"
    }]
}

Now I want to insert another array in the "source_references" if the name and key does not exist in the nested array else don't insert. Here is the result I want,

{ "_id" : ObjectId("50535036381ef82c08000002"),"source_references" : [
    {
            "_id" : ObjectId("50535036381ef82c08000001"),
            "name" : "abc",
            "key" : "123"
    }
    {
            "_id" : ObjectId("50535036381ef82c08000003"),
            "name" : "reuters",
            "key" : "139215"
     }]
}

Here is what I've tried :

$Update_tag = array('$addToSet' => array("source_references.$" => array("name" => "reuters", "key" => $r_id)));
$mycollection->update(array("_id" => $id), $Update_tag);

But I am not able to insert another array inside the nested array. Also I want to create the "_id" field(inside nested array) only if new array inserted in source_references.

Where I am going wrong? Hope I am clear with my question.

6
  • Are you getting any error messages or just the wrong result? Commented Sep 15, 2012 at 6:40
  • I am not getting any error message. simply updation doesn't take place. @JoachimIsaksson Commented Sep 15, 2012 at 6:43
  • A couple of things to check first; you're spelling soruce_references.$ wrong when creating the array, and you have duplicate _id's (reuters & the root) in the expected result. Commented Sep 15, 2012 at 6:53
  • Do you need the embedded _id field in the source_references array if you are already assuming that (name + key) will be unique? Commented Sep 15, 2012 at 6:59
  • @JoachimIsaksson thats not an issue. I manually changed it. I am asking how to insert in such a scenario Commented Sep 15, 2012 at 7:24

1 Answer 1

2

This is tricky because of the unique key that each of the sub-documents has. Therefore, you can't use $elemMatch to check if the key/name pair already exists.

If you're running mongodb 2.2, you can use the aggregation framework to $unwind the nested array, then $match for the key/name pair and insert the new element only if your search returned empty.

This is the php code:

<?php

// connect
$m = new Mongo('localhost:27017');

// select a database and collection
$db = $m->test;
$collection = $db->coll;

// sub-doc to insert if key/name pair doesn't exist
$doc = array('key'=>'12345', 'name' => 'abcde');

// aggregation command (can use $collection->aggregate for driver version 1.3.0+)
$cursor = $db->command(array('aggregate' => 'coll', 'pipeline' => array(
    array('$unwind'=>'$source_references'),
    array('$match' => array('source_references.name' => $doc['name'], 
                            'source_references.key' => $doc['key']))
)));

// if sub-doc doesn't exist, insert into main doc with this objectId
$objectId = '50535036381ef82c08000002';

if (count($cursor['result']) == 0) {
    // insert document with a new ObjectId (MongoId)
    $update_tag = array('$addToSet' => array("source_references" => array("_id" => new MongoId(), "name" => $doc['name'], "key" => $doc['key'])));
    $collection->update(array("_id" => new MongoId($objectId)), $update_tag);
} 

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

1 Comment

before moving further thanks for your answer. Can you please elaborate your answer more so that I can understand a bit more? Does this command works only with mongo-db 2.2? .. because i dont have mongodb-2.2 running.

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.