简体   繁体   中英

php & mongodb: using $addToSet w/ $each

This question is very similar to mine: Is there a way to check if one of the array entries contains a sub-array in MongoDB?

However, in mine, i'm still getting problems with some updates. I'm getting data via an aggregator that pulls in tags. Tags look like this $tags = array("red","green","blue","purple",...);

And my update query looks like this:

$criteria = array('_id' => new MongoId($myID));

$db->aggregation->update($criteria, 
                         array('$addToSet' =>
                            array('tags' =>
                               array('$each' => $tags)))), 
                         true); //add tags

Believe it or not, sometimes it works swimmingly, but sometimes it doesn't. You can see in the below example which ones worked and which didn't.

[74] => red
[75] => orange
[76] => yellow
[77] => green
[78] => Array (
    [$each] => Array (
        [0] => blue
        [1] => indigo
        [2] => purple
    )
)
[79] => violet
[80] => brown
[81] => black

Can anybody explain to me why sometimes this will insert into the collection's array properly, and sometimes it won't? I'm using phpmoadmin (as well as a MongoDB shell version 2.4.3 'find()') to view the results of an insert.

For starters, passing a boolean as the third argument to MongoCollection::update() was deprecated in 1.3.0. In the examples below, I'm using the now-advised $options array as the third and final argument to that method.

Can you verify that the $each key of the 78th array element in your example is exactly those five characters and doesn't include a leading non-printable character? If I prefix $each with chr(13) (ie form feed), MongoDB doesn't pick up that I'm using an operator and will happily add the object argument to the set/array.

Beyond that, the only way I can reproduce the above is by crafting an update where $each 's value is an object:

$c->update(
  ['_id'=>1],
  ['$addToSet' => [
    'tags' => ['$each' => (object) [1,2,3,4,5]],
  ]],
  ['upsert' => true]
);

This results in the following being inserted (using the Mongo shell so we can differentiate between arrays and objects):

{
    "_id" : NumberLong(1),
    "tags" : [
        {
            "$each" : {
                "0" : NumberLong(1),
                "1" : NumberLong(2),
                "2" : NumberLong(3),
                "3" : NumberLong(4),
                "4" : NumberLong(5)
            }
        }
    ]
}

If other elements were already in tags , the above may end up further into the array, like so:

{
    "_id" : NumberLong(1),
    "tags" : [
        NumberLong(1),
        NumberLong(2),
        NumberLong(3),
        NumberLong(4),
        NumberLong(5),
        {
            "$each" : {
                "0" : NumberLong(1),
                "1" : NumberLong(2),
                "2" : NumberLong(3),
                "3" : NumberLong(4),
                "4" : NumberLong(5)
            }
        }
    ]
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM