We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

MongoDb Find and include only specific fields

With the PHP MongoDb Client, the find function allows a second argument to specifiy the fields you want to include in the result.

$cursor = $collection->find(
        array('_id' => array('$in' => $ids)),
        array('_id' => true, 'title' => true, 'subtitle' => true, 'slug' => true, 'description' => true)
);

I'm having trouble trying to do similar with the Phalcon ODM. Is it possible to set field options in the conditions?

$articles = Article::find( 
    array(
        'conditions' => array('_id' => array('$in' => $ids)), 
    )
);


98.9k

An ODM is an Object-Document-Mapper which means that a document must be mapped to a full object, returning only a partial list of columns will produce an incomplete object which when saved will produce unexpected results due to the missing fields in the object. An object must represent its counterpart in the database and vice versa.

Maybe an option to return incomplete objects could be added in a further release.



3.6k

This seems to be a much needed feature. Unless terribly mistaken, I believe that executing a query that returns specific fields falls in the realm of an ODM.

Is there an authoritative source on the matter?



98.9k

We already have implemented a solution in the ORM, but here there is the same problem.

Let's pretend we already support that feature:

//Save an article with all its fields
$article = new Article();
$article->title = "hello";
$article->content = "what is the content";
$article->save();

//Get the article but only 'title'
$article = Article::findFirst(array(
    'fields' => array('title')  
));

//How do we save the record if "_id" is not available because it wasn't queried?
//What should be the behavior saving this if 'content' was initially set but now it isn't available?
$article->save();


3.6k

Since I have just been a user of ORMs, I would like to take the time to explore the topic further before I can continue this discussion. From my research, it seems that Martin Fowler's book on enterprise patterns is a good start. I would not want to offer a feature just for the sake of being available and with no proper justification.

To address your questions. There is a fortunate effect of calling find() on the PHP driver. It always returns _id. For the second question, that example can be pushed further and use the already available aggregation with some form of projection. That could introduce set of problems.



98.9k

We can return stdClass instances instead of Article instances (when a partial list of fields are requested), this is how we treat that issue in the ORM. Of course, stdClasses are only intended to read purposes, those cannot be saved due to the missing fields.



12.3k

Yes, my intent was only for greater efficiency in read only situations where I only need a few of the fields rather than the whole document. For example, I'd be querying a collection of articles where I would like to generate a list of the links to each article and do not need to pull the entire article text. MongoDb is completely new to me, though, so maybe I should not be using the ODM for this, but should query directly through the PHP Mongo Client. In the SQL world, I've used some ORM (a little Yii and PHPActiveRecord). It's great for the typical CRUD. But larger results, I just do raw queries and use a row mapping function. Anyhow, when dumping the enormous resulting object of an ORM query I I thought I saw booleans set on the columns for each record to denote which could be saved/updated.



3.6k

@Phalcon That seems like a very reasonable solution. Thank you for your hard work. Always appreciated. @netblue I use the PHP Mongo Client right now for such queries since I have documents that are 2-5 MB each.



199

Hello....

Not familiar with MongoDB but here is a possible resource.... Hope it will help... :-)

https://zappysys.com/blog/ssis-loading-data-into-mongodb-upsert-update-delete-insert/