update(array("loc1"=>$locations[0]),array('$set'=>(object)array("Users"=>(array("user_id"=>$user_id,"user_name"=>$Email)))));
I wrote the above code to insert user_id to the array users, after execution i got the result in mongodb shown below
{
"_id" : ObjectId("5702cfd2c693b54008000035"),
"loc1" : "Anapara",
"loc2" : "Puthucurichy",
"loc3" : "Kadinamkulam",
"loc4" : "Kerala",
"loc5" : "India",
"Users" : {
"user_id" : ObjectId("5702cfd2c693b54008000034"),
"user_name" : "chunks#yahoo.com"
}
}
Here the keyword Users is not becoming an array, i mean i want it in this format (value of user in a square bracket):
"Users" :[ {
"user_id" : ObjectId("5702cfd2c693b54008000034"),
"user_name" : "chunks#yahoo.com"}
]
What modification should i do in my php code to put the values in square bracket?
BSON array ([ ... ]) can be saved from PHP if you use an array indexed by consecutive numbers (a list). So your code needs to be (I'll allow myself to make it more readable to illustrate better):
update(
array("loc1" => $locations[0]),
array('$set' => array(
"Users"=> array( // this makes Users a list
array("user_id"=>$user_id,"user_name"=>$Email) // this is your embedded object
// here could go another embedded object separated by a comma
)
))
);
Related
I am trying to created an error checking routine for an inbound JSON file in PHP. The file that should produce an error is encoded as;
{
"id" : 4,
"id" : 3,
"id" : 2,
"id" : 1
}
How do I detect that "id" is used more than once instead of just letting the last value of id make it to the JSON object? This is my overly simplistic code;
$data = json_decode(file_get_contents("php://input"));
print_r($data);
it produces the result;
stdClass Object
(
[id
] => 1
)
Other than testing the string with substr_count() for multiple instances of '"id"' is there a better (more efficient?) way to accomplish this task?
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 :-)
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))),
));
I have the following data structure in MongoDB:
{ "_id" : ObjectId( "xy" ),
"litter" : [
{ "puppy_name" : "Tom",
"birth_timestamp" : 1353963728 },
{ "puppy_name" : "Ann",
"birth_timestamp" : 1353963997 }
]
}
I have many of these "litter" documents with varying number of puppies. The highter the timestamp number, the younger the puppy is (=born later).
What I would like to do is to retrieve the five youngest puppies from the collection accross all litter documents.
I tried something along
find().sort('litter.birth_timestamp' : -1).limit(5)
to get the the five litters which have the youngest puppies and then to extract the youngest puppy from each litter in the PHP script.
But I am not sure if this will work properly. Any idea on how to do this right (without changing the data structure)?
You can use the new Aggregation Framework in MongoDB 2.2 to achieve this:
<?php
$m = new Mongo();
$collection = $m->selectDB("test")->selectCollection("puppies");
$pipeline = array(
// Create a document stream (one per puppy)
array('$unwind' => '$litter'),
// Sort by birthdate descending
array('$sort' => array (
'litter.birth_timestamp' => -1
)),
// Limit to 5 results
array('$limit' => 5)
);
$results = $collection->aggregate($pipeline);
var_dump($results);
?>
I am trying to find a record in mongoDB by it's MongoID "_id" field. I have found examples on how to do it, but can not get it to work. Example:
$recID = "010101010101011"; //would be a valid mongodb _id
$recID = new MongoId((string)$recID); // I have tried it without the (string) cast too
$cursor = $this->Collection->findOne(array('_id' => $recID));
print_r($cursor);
It outputs:
MongoCursor (
)
Nothing inside.
I have verified everything else is working by changing the "_id" above to a different field such as "firstName" and passing in a first name and I get back valid data.
Why does this not work?
I have even tried searching with $recID as a string, no difference.
Here is what happens from the mongo shell (though I am not sure if I am querying properly):
>
> db.Employee.find({login:"myperson"})
{ "_explicitType" : "project.Employee", "_id" : ObjectId("4e209564203d83940f0000
06"), "active" : true, "addedDate" : "07/15/2011 15:29:21", "domain" : "xxx",
"id" : ObjectId("4e209564203d83940f000006"), "lastLogin" : "07/20/2011 19:13:36
", "login" : "myperson", "name" : "My Person", "pw" : "", "ulevel" : 9999
}
> db.Employee.find({id:"4e209564203d83940f000006"})
> db.Employee.find({_id:"4e209564203d83940f000006"})
>
Notice nothing returned for id or _id.
Try db.Employee.find({_id:ObjectId("4e209564203d83940f000006")}
you can wrap your id around a ObjectID wrapper. This tells mongo db your looking for a specific column the _id column.
var ObjectID=require('mongodb').ObjectID;
then do
collection.findOne({_id: ObjectID(id)},function(err,user){ //blah blah}