Update a couple of values in nested array MongoDB - php

I would like to update a couple of elements in they match given values:
Example : I have a collection with this structure:
{
"_id" : ObjectId("52936a0270c68c04063f0300"),
"channel" : "1",
"content" : "145548",
"keywordsValues" : [
[ObjectId("52816d3370c68c2c1c4b0500"), ObjectId("52816d3370c68c2c1c9f0500")],
[ObjectId("52816d3370c68c2c1c510500"), ObjectId("52816d3370c68c2c1c890500")],
[ObjectId("52816d3370c68c2c1c550500"), ObjectId("52816d3370c68c2c1c850500")],
[ObjectId("52816d3370c68c2c1c6b0500"), ObjectId("52816d3370c68c2c1c990500")]
]
}
And I need to update "keywordsValues" field (just one of the couple in the array [])
Something for example update the 2nd element in keywordsValues:
If we found [firstId,secondId] in keywordsValues field then update the second secondId
$database->Measurements->update(
array('keywordsValues'=>
array(new MongoId(52816d3370c68c2c1c4b0500),new MongoId(52816d3370c68c2c1c9f0500)',$atomic'=>'true')),
array('$set'=>array('keywordsValue.$'=>new MongoId($idNewValue))));
But this doesn't work...

try
array('$set'=>array('keywordsValue'=>new MongoId($idNewValue))));
instead of
array('$set'=>array('keywordsValue.$'=>new MongoId($idNewValue))));
i hope it help to you!

Related

MongoDB+Doctrine ODM How to remove a embedded document in a document collection?

im using mongoDB with Doctrine ORM and want to remove the embedded document "avatar" (or set it to null) in a document collection.
My Json-Object looks like this:
{
"_id" : ObjectId("55965d090203ff700f000032"),
"name" : "test",
"stores" : [
{
"_id" : ObjectId("559d166f0203ff081300002f"),
"storeName" : "test",
"openingTimes" : "",
"address" : {
...
},
"contactPerson" : {
"firstname" : "",
"lastname" : "",
...
"avatar" : {
"source" : "/uploads/images/company/55965d0980585/contactPerson/",
"name" : "contactperson.jpg"
}
}
},
...
]
}
Im using the queryBuilder and try something like this
$company = $this->getQueryBuilder()
->findAndUpdate()
->field('stores')->equals($store)
->field('contactPerson.avatar')->set(null)
->getQuery(array('multiple' => true))
->execute();
But it does´t work. How can i get access to the avatar key?
You can use the equivalent of $unset in the core operators to do this example. Where I would actually suggest for brevity and safety to use:
$company = this->getQueryBuilder()
->findAndUpdate()
->field('stores._id')->equals($storeId)
->field('stores.$.contactPerson.avatar')->unsetField()->exists(true)
->getQuery()
->execute();
Where you just hold on to the _id value from the element in the "stores" array that you actually want and this helps match the position of the array element you need to remove that document to.
Also using "dot notation" for the embedded document path.
That "removes" the "key" from the document rather than just setting it to null.
If you want "mutiple" then you want .update() instead, but this does not return the object.
Ughh!
To select things you just use:
$company = this->getQueryBuilder()
->find()
->field('stores._id')->equals($storeId)
->select('stores.$.contactPerson.avatar')-
->getQuery()
->execute();
I don´t know if it´s the best way but this one works for me
$company = $this->getQueryBuilder()
->findAndUpdate()
->field('_id')->equals($company->getId())
->field('stores.'.$key.'.contactPerson.avatar')->set(null)
->getQuery()
->execute();
line 3: get the parent object by id (not store)
line 4: get the store by $key. Then i can use ->set(null) to set the embedded Object to null or to remove it with
->field('stores.'.$key.'.contactPerson.avatar')->unsetField()->exists(true)
#Blakes Seven: Thanks for your helpful answer :-)

Using $all to match values inside an array inside of another array

I have the following mongo document structure
"search": [
[
"keyword",
"match"
],
[
"testing",
"something",
"serious"
]
]
I want to find documents where the array of keywords inside of the array match an $all query.
E.g if search had only 1 level I would do
{'search': {'$all': ['keyword','match']}}
I've tried using:
{'search': {'$elemMatch': {'$all': ['keyword','match']}}}
But I get no results.
If you know the array of keywords in advance and you want to match a document that contains that array inside the search array, you can just use a simple query as follows.
db.collection.find({"search": ["keyword", "match"]});
That should return your sample document. On the other hand, if the array is not completely contained by an element inside search, it will not return anything. For example the following query will not return your sample document.
db.collection.find({"search": ["keyword", "match", "testing"]});

collection not add pushing to subarray

I am using MongoDB and in the past I have been able to use the following to insert or add to a sub array that was already in the DB
Here is my issue, every day we take a look at the itunes top 100 and we insert the songs and artist into our collection, well infact we use two collections to do this job
but the one I am having issue with is the one that we store every single song and artist that has ever appeared in the iTunes top 100.
see code below
$collection = static::db()->itunes_collection_australia;
$document = $collection->findOne(array('song' => (string)$entry->imname, "artist"=>(string)$entry->imartist));
if (null !== $document) {
$collection->update(
array(array('song' => (string)$entry->imname, "artist"=>(string)$entry->imartist)),
array('$push' => array("date" => array('$each'=> array((string)$date)),"chartno"=> array('$each'=> array($a))),
));
}
else
{
$collection->insert(array("song"=>(string)$entry->imname, "artist"=>(string)$entry->imartist,"preview"=>(string)$preview,"cd_cover"=>(string)$cover, "price"=>(string)$price,"date"=>array((string)$date),"chartno"=>array($a)));
}
what should be happening is if the artist and song is found to already be the the collection , it should update. at the moment it is not running anything.
and if it is updating its not doing it right.
You see the "date" field should be showing multiple dates same with the chartno it should also be showing what position it was in the charts on that day.
here is how it should look when first inserted.
{
"_id" : ObjectId("52ea794d6ed348572d000013"),
"song" : "Timber (feat. Ke$ha)",
"artist" : "Pitbull",
"preview" : "http://a1264.phobos.apple.com/us/r1000/030/Music6/v4/48/30/3c/48303ca0-c509-8c15-4d4a-7ebd65c74725/mzaf_5507852070192786345.plus.aac.p.m4a",
"cd_cover" : "http://a1082.phobos.apple.com/us/r30/Music6/v4/64/41/81/644181ba-d236-211d-809e-057f4352d3d8/886444273480.170x170-75.jpg",
"price" : "$2.19",
"date" : [
"2014-01-29T07:10:38-07:00"
],
"chartno" : [
20
]
}
when the script sees it is back in the top 100 it should add it to the date and chartno fields.
like so
{
"_id" : ObjectId("52ea794d6ed348572d000013"),
"song" : "Timber (feat. Ke$ha)",
"artist" : "Pitbull",
"preview" : "http://a1264.phobos.apple.com/us/r1000/030/Music6/v4/48/30/3c/48303ca0-c509-8c15-4d4a-7ebd65c74725/mzaf_5507852070192786345.plus.aac.p.m4a",
"cd_cover" : "http://a1082.phobos.apple.com/us/r30/Music6/v4/64/41/81/644181ba-d236-211d-809e-057f4352d3d8/886444273480.170x170-75.jpg",
"price" : "$2.19",
"date" : [{
"2014-01-30T07:10:38-07:00"
},{2014-01-31T07:10:38-07:00}],
"chartno" : [
{20},{30}
]
}
however that is not happening infact nothing seems to be getting added.
I am wondering if I have done something wrong? Well clearly I have.
I have also tried the following '$addToSet' but with no success.
your update statement is wrong. you have too many arrays on first parameter. try this:
$collection->update(
array('song' => (string)$entry->imname, "artist"=>(string)$entry->imartist),
array('$push' => array("date" => array('$each'=> array((string)$date)),"chartno"=> array('$each'=> array($a))),
));

Query mongodb with php-mongo

I am building a simple messaging system, and i have a collection in mongodb with documents like this:
{ "_id" : ObjectId("50ad003f9811e5bc5c000000"), "between" : [ "user1,user2,user3" ] }
I want to perform this query:
db.conversations.find({'between': ["user1,user2,user3"]});
to get this exact document back. This query works in mongo shell.
in php-mongo, i tried this:
$collection->find(array("between"=>array("user1", "user2", "user3")));
but it does not work.
What am i doing wrong ?
Wouldn't you want to do an In query here?
db.collection.find( { "between" : { $in : ["user1", "user2", "user3"] } } );
See In query here:
Mongo Advanced $in query
making your PHP query look like:
$collection->find(array("between"=>array("$in"=>array("user1", "user2", "user3"))));
//untested, should be something similar to this.
or if you're trying to find it exactly wouldn't you just be able to do:
$collection->find(array("between"=>array("user1,user2,user3")));
First of all when you are saving your data you have to use array not a string
{ "between" : [ "user1,user2,user3" ] }
this stores in "between" an array of one element "user1,user2,user3"
Basically when you do your query in shell everything is ok, because you are asking for a array with one element. But in php you are asking for an array of three elements.
So, when you save your data, most probably that is what you need :
{ "between" : [ "user1","user2","user3" ] }
and this will give you an array of three users.
Then read the documentation http://www.mongodb.org/display/DOCS/Advanced+Queries to and adjust your query depends on what you need: either the exact array or only some elements in the array
Have you tried:
$collection->find(array("between"=>"user1,user2,user3"));
or
$collection->find(array( "$elemMatch" => array( "between"=>"user1,user2,user3" ));
The $in operator is analogous to the SQL IN modifier, allowing you to specify an array of possible matches.
Consider the following example which uses the $or operator.
$collection->find([
'select' => ['$in' => ['option 1', 'option 2', 'option 3']]
]);
References

Remove item from an array Options - Mongodb

How would you remove an array item from a mongodb field . For example , how do i remove guitar from the list of interest . Any PHP functions or approaches would help.
{
"_id" : ObjectId("4d1cb5de451600000000497a"),
"name" : "dannie",
"interests" : [
"guitar",
"programming",
"gadgets",
"reading"
]
}
unset($array['interests']['guitar']) if this is array in PHP
you can use unset() function for this task.
Thanks.
Actually it should be
$key = array_search('guitar', $array['interests']);
unset($array['interests'][$key]);
as guitar is not a key for interests.

Categories