Comments (5)
Hello.
ODM tries to map mongo's document to object. Any field of document in collection mapped to property of Sokil\Mongo\Document
object, any embedded document mapped to Document
property, also as field of embedded document.
If you do not configure your Document
class to map embedded document to some Structure
, it will be just array.
But you can do some tricks to get embedded document like object: https://github.com/sokil/php-mongo#embedded-documents, so in this way your Document
became aggregate of another embedded documents.
In first example, when you query collection using $collection->findAsArray()
with whereElemMatch
, you get whole aggregate with all embedded documents inside, but only if this whole aggregat contain some fields in it's embedded documentys. Because you filtered by _id
and embedded classes
containing other id.
In second example, when you call native findOne
, you pass second projection
parameter:
https://docs.mongodb.com/v3.2/reference/method/db.collection.findOne/.
<?php
$result = $collection->getMongoCollection("Project")->findOne(
// query
array(
"_id" => new MongoId("59f889e46803fa3713454b5d")
),
// projection
array(
"classes" => array(
'$elemMatch' => array(
"_id" => new MongoId("59f9d7776803faea30b895dd")
)
)
)
);
This code find document by _id
and project some fields.
Find by id with bool projection:
> db.test.findOne({"_id": ObjectId("59f889e46803fa3713454b5d")}, {classes: 1})
{
"_id" : ObjectId("59f889e46803fa3713454b5d"),
"classes" : [
{
"_id" : ObjectId("59f9d7776803faea30b895dd"),
"className" : "OLA"
},
{
"_id" : ObjectId("59f9d8ad6803fa4012b895df"),
"className" : "HELP"
},
{
"_id" : ObjectId("59f9d9086803fa4112b895de"),
"className" : "DOC"
},
{
"_id" : ObjectId("59f9d9186803fa4212b895de"),
"className" : "INVOC"
}
]
}
Due to https://docs.mongodb.com/manual/tutorial/project-fields-from-query-results/#project-specific-array-elements-in-the-returned-array you can also project by some expressions:
Find by id and id of embedded document of "classes":
> db.test.find({"_id": ObjectId("59f889e46803fa3713454b5d")}, {"classes": {$elemMatch: {"_id" : ObjectId("59f9d9086803fa4112b895de")}}}).pretty()
{
"_id" : ObjectId("59f889e46803fa3713454b5d"),
"classes" : [
{
"_id" : ObjectId("59f9d9086803fa4112b895de"),
"className" : "DOC"
}
]
}
Currently $elemMatch
not supported. You can only $slice
and project specific fields. And this feature require to beimplemented.
from php-mongo.
yes, this feature will be implemented. Thanks for interesting lib )
from php-mongo.
Implemented in v.1.22.2
Useage:
public function testElemMatch()
{
// create new document
$this->collection
->createDocument(array(
"_id"=> new \MongoId("59f889e46803fa3713454b5d"),
"projectName" => "usecase-updated",
"classes" => array(
array(
"_id" => new \MongoId("59f9d7776803faea30b895dd"),
"className" => "OLA"
),
array(
"_id" => new \MongoId("59f9d8ad6803fa4012b895df"),
"className" => "HELP"
),
array(
"_id" => new \MongoId("59f9d9086803fa4112b895de"),
"className" => "DOC"
),
array(
"_id" => new \MongoId("59f9d9186803fa4212b895de"),
"className" => "INVOC"
)
)
))
->save();
// filter embedded documents
$filteredClasses = $this->collection
->find()
->elemMatch(
'classes',
function(Expression $e) {
$e->where('_id', new \MongoId("59f9d9186803fa4212b895de"));
}
)
->one()
->classes;
$this->assertEquals(
'INVOC',
$filteredClasses[0]['className']
);
}
from php-mongo.
I tried using aggregation framework and comes up with following query:
$result = $collection->aggregate(array(
array(
'$match' => array(
"_id" => new MongoId("59f889e46803fa3713454b5d")
)
),
array(
'$project' => array(
'classes' => array(
'$filter' => array(
'input' => '$classes',
'as' => 'classItem',
'cond' => array(
'$eq' => array('$$classItem._id' => new MongoId("59f9d7776803faea30b895dd"))
)
)
)
)
)
));
its giving me following exception:
Sokil\\Mongo\\Exception\nMessage: Aggregate error: Unrecognized expression '$$classItem._id'\nFile:
is there any syntax error?
from php-mongo.
Thank you for the detailed answer. I wanted to move toward the mapping of ODM to a class so i will try it with the mapping functionality. Moreover as you mentioned that $elemMatch
is not yet implemented so this mean this post can be labeled as enhancement for the development of $elemMatch
.
One more update is that I tried with aggregation query and somehow i was able to retrieve desired results. I was making a mistake in the syntax of the aggregation query. Following is my updated aggregation query for retrieving matched embedded document (i am using $filter
array aggregation function):
$collection = $PHPMongoDBInstance->getCollection("Project");
$result = $collection->aggregate(array(
array(
'$match' => array(
"_id" => new MongoId('59f889e46803fa3713454b5d')
)
),
array(
'$project' => array(
'classes' => array(
'$filter' => array(
'input' => '$classes',
'as' => 'class',
'cond' => array(
'$eq' => array('$$class._id', new MongoId("59faff836803fa3b1203d2e5"))
)
)
),
'projectName' => 1
)
)
));
the problem was in the syntax of the following expression:
'$eq' => array('$$classItem._id' => new MongoId("59f9d7776803faea30b895dd"))
I learned that it shouldn't be a associative array rather each element in the expression should be a separate array item like this:
'$eq' => array('$$class._id', new MongoId("59faff836803fa3b1203d2e5"))
With this conclusion i am able to get the results correctly.
from php-mongo.
Related Issues (20)
- Batch operations coverage
- Regexp in whereNot expression HOT 1
- Psr-16
- Creating collection and options
- Allow add custom validation engine
- mess detecor
- Extract symfony event dispatcher and allow to replace it
- install problem HOT 2
- Document 'afterConstruct' event not triggered properly HOT 1
- how to change enviroment by command line. HOT 1
- Making behaviors work with Document events HOT 2
- Allow add event handlers to collection definition in mapping
- Support of plain old php class documents
- Uncaught Error: Class '\MongoCollection' not found HOT 2
- Which PHP version do you use?
- Is it possible to renameCollection? HOT 3
- Configure code style, fix current codestyle bugs
- Get one document with sorting HOT 1
- "Undefined index: ok" when i try to aggregate
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from php-mongo.