I have a problem with aggregation function:
this is a screen from MongoDB Compass:
Category structure:
{
'title' => 'Sport'
'articles' => [
{
'title' => 'My title'
'status' => 'published'
}
]
....
}
In the screen you can see a filter in order to get all categories with at least an article with status published.
In the result I always see also category with 'status' => 'draft'. I do not understand why this filter is not working.
How can I solve this?
Thanks
Related
Hi i am working on backend of web application & want to find the documents from mongodb database that contain key active_status with value set to both 1 & 2. With mongodb PHP i am confused of how to find with both parameters in single query.
My query was this:
$mongoDb = MongoDbConnector::getCollection("endusers");
$endUserData = $mongoDb->find(array('active_status' => 1, '$and' => array('active_status' => 2)));
I have to fetch the users whose active_status should be 1 & 2. The above query doesnt seems to work. What is the right one for that?
Thanks on advance for quick response.
You have $and the wrong way around. Both arguments need to be included:
$endUserData = $mongoDb->find(array(
'$and' => array(
array( 'active_status' => 1 )
array( 'active_status' => 2 )
)
));
And since that would only make sense when looking for both elements within an array element, then you should instead use $all, which is shorter syntax:
$endUserData = $mongoDb->find(array(
'active_status' => array( '$all' => array(1,2) )
));
I should add that unless you intend to match a document like this:
{ "active_status" => [1,2] }
The you do not in fact want $and at all, but rather you want $or or better yet $in for multiple possible values on the same field:
$endUserData = $mongoDb->find(array(
'active_status' => array( '$in' => array(1,2) )
));
This matches documents like this:
{ "active_status": 1 },
{ "active_status": 2 }
The following is the json array I have in a collection called claims in MongoDB.
{
"xmllisting_id": "537f371fb2e380922fff0e2c",
"pharmacyfiles_id": "537f3402b2e380732aa6032d",
"claim": {
"MemberID": "097110330047532601",
"PatientShare": "0",
},
"modified": ISODate("2014-05-23T13:12:17.191Z"),
"created": ISODate("2014-05-23T13:12:17.192Z")
}
I need to find all claims with a specified MemberID.I have tried the following in CakePHP without any success.
$claims = $claimobj->find(
'all',
array(
'conditions' => array(
'claim' => array('MemberID' => '097110330047532601')
)
)
);
How can I do it?
Finding "nested" details in MongoDB usually requires "dot notation". Otherwise you are actually asking for an object that has "exactly" the key and "only" the key you are specifying to match. Which of course it does not, as there is more information there:
$claims = $claimobj->find(
'all',
array(
'conditions' => array(
'claim.MemberID' => '097110330047532601'
)
)
);
So the path is "claim.MemberID" and not 'claim' => array('MemberID' => '097110330047532601' ) as you have written.
how can I work with lists within the mongoDB?
For example, I have a document (class), and a list of students in this class, ie a subdocument (students).
What do not you, is to add more students to a class.
in Model:
public function salvar($name,$idClass){
$new = array(
"_id" => $idClass,
"student"=> array(
'idStudent' => new MongoId(),
'name' => $name));
return $this->save($new);
}
But when you add a new student, he is not working that way.
How to perform a $push update
The answer you've provided clarifies what you've been trying to do. However, the solution is a little convoluted. To perform a $push update with MongoDB, simply specify you want to perform a push update:
$this->Foo->save(array(
'_id' => $id,
'$push' => array(
"images" => array(
'id' => new MongoId(),
'name' => $name,
'size' => $size
)
)
);
You can use the mongoNoSetOperator property to achieve the same thing but
It's indirect, therefore not obvious
With multiple calls to save in the same request it can be confusing if it's not reset to $set if it's modified
It prevents using multiple operators in a single call.
There's more information about using different update operators in the documentation.
the answer to the question was:
public function salvar($name,$size,$id){
$this->mongoNoSetOperator = '$push';
// fixed array data structure
$susp = array(
"_id" => $id,
"images"=> array(
array(
'id' => new MongoId(),
'name' => $name,
'size' => $size
)
)
);
return $this->save($susp);
}
Note: Thank Garamon from github, by clear and objective answers.
I would appreciate the help here. For the purpose of this discussion I have an example here (I will use paste bin for the codes):
http://pastebin.com/VPuyKn6W
I am trying to produce this output:
http://pastebin.com/4iMLacRu
I understand that I need to use $push to make this work. But upon testing, it doesn't seem to do anything. I am following the instructions as prescribed in the docs, but instead of using $Id, I am using user_id for finding the document in the collection. Here is my model:
http://pastebin.com/QB94tbZn
Am I misunderstanding something, or I am not using the $push operator properly, or something to do on how I created the document?
After walking outside, I finally got my answer.
public static function create_mongo()
{
$data = array(
'user_id' => '123895',
'First_Name' => 'John',
'Last_name' => 'Doe',
'sites' => array(
array(
'title' => 'Sankaku Complex',
'site' => 'http://sankakucomples.com'
)
)
);
$db = Fuel\Core\Mongo_Db::instance();
$db->insert('test_collection',$data);
}
sites should be an array carrying an array variable.
I'm using lithium with mongodb and I would like to know with my models below how I could get the data of the user from Posts::find('all'); query?
Do I have to do two queries?
Thanks for your help!
<?php
namespace app\models;
class Posts extends \lithium\data\Model {
protected $_schema = array(
'_id' => array('type' => 'id'),
'name' => array('type' => 'string', 'null' => false),
'description' => array('type' => 'string', 'null' => false),
'created' => array('type' => 'datetime'),
'updated' => array('type' => 'datetime'),
'user_id' => array('type' => 'integer')
);
protected $_meta = array(
'key' => '_id',
);
public $belongsTo = array('Users');
}
?>
<?php
namespace app\models;
class Users extends \lithium\data\Model {
public $hasMany = array('Posts');
public $validates = array(
'name' => 'Please enter a name',
);
protected $_schema = array(
'_id' => array('type' => 'id'),
'name' => array('type' => 'string', 'null' => false),
'slug' => array('type' => 'string', 'null' => false),
'created' => array('type' => 'datetime', 'null' => false),
);
}
?>
Currently relationships only exist for relational databases like MySQL and SQLite3. As such you'll need to make two queries to get the data you want. We're working on adding support for relationships for document based databases now however there currently is no timeframe on that.
You can use Set::extract on your result from posts to pull all of the user id's out then use the results from that to make a single query from users - so from posts you could do $userIDs = Set::extract('/posts/user_id', $posts->data()); then User::find('all', array('conditions' => array('_id' => $userIDs)));
hope this helps.
edit: You can find set::extract information here: http://li3.me/docs/lithium/util/Set::extract()
Do I have to do two queries?
This will depend on your schema.
Case #1
If Users and Posts are two different collections then you will need two different queries.
Case #2
If Users is the top level object and Posts "belongs to" Users then you would do something equivalent to db.users.find({ posts : {$exists:true} }).
I'm not 100% clear on how Lithium handles this. I cannot find a simple example of whether Lithium is doing #1 or #2.
As Howard3 said, there is currently no relationship support for MongoDB and as a result "belongs to" won't work either.
The actual decision depends on your application, but i assume that its going to be some form of a blog (users and posts). According to MongoDB schema design best practices, i'd put both in separate collections because they are "first level collections". a better fit for embedded documents would be posts and comments.
Also, you don't have to define the 'key' stuff when you're on latest master. You can write a custom find method for now that could be easily swapped to the more generic solution when relation support is finished in the core.
if you need more interactive help, visit #li3 on freenode.