PHP Mongodb - Sort Query based on nested objects - php

I am fairly new to PHP and working with a MongoDB, so please be patient :)
This is an example of what I am trying to do, not the actual data, so hopefully this helps!
I have a MongoDB Collection that has nested objects in it and I want to sort the results of a query based on one of the nested fields.
Sample row from the DB via MongoDB Compass:
_id:"12345"<br>
houses:Object<br>
> 124 Happy St.:Object<br>
> name:"124 Happy St."<br>
> price:"$123,000"<br>
> 123 Happy St.:Object<br>
> name:"123 Happy St."<br>
> price:"$124,000"<br>
> 125 Happy St.:Object<br>
> name:"125 Happy St."<br>
> price: "$200,000"<br>
I want to be able to sort my query based on the price field (highest to lowest) in the houses object.
I've tried the following but I can't see to get the results to return sorted as expected - remember, I'm not that strong yet with PHP and MongoDB so go easy on me :P
$houses_query = new MongoDB\Driver\Query([ "_id" => "12345" ], [ 'sort' => [ 'houses.price' => 1 ]])
Is there a way to filter the query or do I have to read the rows into an array and sort that way?

Absolutely, mongoDB has a robust sort algorithm and tools like sort, order_by etc. You can do with php arrays but mongoDB has a lot of blessings :)
I did similar solution nowadays, you could do like this (your mongo class can be diffrent)
$videos = $this->mongo_db->where(
array('$text' => array('$search' => $q),
'status' => 1))
->order_by(array('video_sales' => 'desc'))
->get('videos');
Mongo documentation says to us;
db.collection.find().sort( { age: -1 } )
Deprecated in the mongo Shell since v3.2
Starting in v3.2, the $orderby operator is deprecated in the mongo shell. In the mongo shell, use cursor.sort() instead.

Related

What is better on Performance when Querying 50 GB data ? Is it MYSQL SELECT with a condition or Dynamodb SCAN with FiLTER Expressions?

I'm retrieving some traffic data of a website using "scan" option in Dynamodb. I have used filterExpression to filter those out.
I will be doing scanning against a large table which will have more than 20GB of data.
I found that DynamoDB scans throguh the entire table and filter the results out. The document says it only returns 1MB of data and then i have to loop through again to get the rest. It seems to be bad way to make this work.
got the reference from here: Dynamodb filter expression not returning all results
For a small table that should be fine.
MySQL dose the same I guess. I'm not sure.
Which is faster to read is it MySQL select or DynamoDB scan on a large set of data. ?
Is there any other alternative? what are your thoughts and suggestions?
I'm trying to migrate those traffic data into Dynamodb table and then query it out. It seems like a bad idea to me now.
$params = [
'TableName' => $tableName,
'FilterExpression' => $this->filter.'=:'.$this->filter.' AND #dy > :since AND #dy < :now',
'ExpressionAttributeNames'=> [ '#dy' => 'day' ],
'ExpressionAttributeValues'=> $eav
];
var_dump($params);
try {
$result = $dynamodb->scan($params);
After considering the suggestion this is what worked for me
$params = [
'TableName' => $tableName,
'IndexName' => self::GLOBAL_SECONDARY_INDEX_NAME,
'ProjectionExpression' => '#dy, t_counter , traffic_type_id', 'KeyConditionExpression' => 'country=:country AND #dy between :since AND :to',
'FilterExpression' => 'traffic_type_id=:traffic_type_id' 'ExpressionAttributeNames' => ['#dy' => 'day'],
'ExpressionAttributeValues' => $eav
];
If your data is like Key-Value pair and you have fixed fields on which you want to index, use DynamoDB - you can create indexes on all fields you want to query and it will work great
If you require complex querying on multiple indexes, then any RDBMS is good.
If you can query on just about anything, think about Elastic search
If your queries are very simple, but you have large data to be retrieved in each query. Think about S3. Maybe you can index metadata in DynamoDb and actual data can be in S3

PHP Mongodb Count Result

I'm performing a simple request to my MongoDB in php. It looks like this:
$result = $this->myMongoClient->myCollection->find([
'param_1' => $param_1,
'param_2' => $param_2,
]);
This returns a MongoDB\Driver\Cursor object. I need the count of returned entrys from the database.
I've googeld a while and found this. But with this function dose not exists on the object returend by MongoDB (Call to undefined method MongoDB\Driver\Cursor::count())
$result->count()
Which is the commun way to count the number of results?
I have found a solution, but don't know if it is recommendable or not.
count($result->toArray());
I don't know if you are using the MongoDB PHP Library, but if you are you can just use the following
$result = $this->myMongoClient->myCollection->countDocuments($where);
https://docs.mongodb.com/php-library/master/reference/method/MongoDBCollection-countDocuments/index.html

Query (find many) documents from multiple collections with the same document structure (MongoDB & PHP)

I use MongoDB PHP v1.3 and in my MongoDB I have multiple collections:
// COLLECTION NAMES:
- user_1_list_1
- user_1_list_2
- user_1_list_3
...
- user_1_list_55
All these collections have the same document-structure:
{
first_name
last_name
phone
}
How can I query the documents from all of these collections at the same time? In the documentation, it is explained how to query (find many) documents from one collection: https://docs.mongodb.com/php-library/v1.3/tutorial/crud/#find-many-documents.
For example, in my case, it would look something like this:
$collection_name = "user_1_list_1";
$collection = $this->db->{$collection_name};
$query = [];
$cursor = $collection->find(
$query,
[
'limit' => 10,
'skip' => 0,
'sort' => ['first_name' => 1],
]
);
... but this will find documents only from one collection (in this case, only from the collection with name "user_1_list_1").
How to find documents from all of these collections (user_1_list_1, user_1_list_2, user_1_list_3 ... ) (that have the same structure), not just from one specific?
Is this possible at all? If yes, how would you do that?
MongoDB is not a relation database and there is no good solution for your case.
You can get your collections and loop over it (but it’s a not good
solution).
You can change your database structure and use one collection with embedded
data

php Mongo driver cursor traveling take long so much

I have a query like this
$results = $collection->find([
'status' => "pending",
'short_code' => intval($shortCode),
'create_time' => ['$lte' => time()],
])
->limit(self::BATCH_NUMBER)
->sort(["priority" => -1, "create_time" => 1]);
Where BATCH_SIZE is 70.
and i use the result of query like below :
foreach ($results as $mongoId => $result) {
}
or trying to convert in to array like :
iterator_to_array($results);
mongo fetch data and traveling on iterate timing is :
FetchTime: 0.003173828125 ms
IteratorTime: 4065.1459960938 ms
As you can see, fetching data by mongo is too fast, but iterating (in both case of using iterator_to_array or using foreach) is slow.
It is a queue for sending messages to another server. Destination server accept less than 70 documents per each request. So i forced to fetch 70 document. anyway. I want to fetch 70 documents from 1,300,000 documents and we have problem here.
query try to fetch first 70 documents which have query conditions, send them and finally delete them from collection.
can anybody help? why it takes long? or is there any config for accelerating for php or mongo?
Another thing, when total number of data is like 100,000 (isntead of 1,300,000) the traveling is fast. traveling time will increase by increasing number of total documents.
That was because of sorting.
The problem :
Fetching data from mongo was fast, but traveling in iterator was slow using foreach.
solution :
there was a sort which we used. sorting by priority DESC and create_time ASC. These fileds was index ASC seperatly. Indexing priority DESC and create_time ASC together fixed problem.
db.queue_1.createIndex( { "priority" : -1, "create_time" : 1 } )
order of fileds on indexing is important. means you should use priority at first. then use create_time.
because when you try to sort your query, you sort them like below :
.sort({priority : -1, create_time : 1});

EMongoCriteria : Limit and Group By show less rows

I am using MongoDB, with PHP YII. I have used YiiMongoDbSuite for setting up the criteria for mongoDB Queries.
Currently, I am using Group by and Limit together. But due to some reason queries are returning less number of rows than that are expected.
$criteria=new EMongoCriteria();
$criteria->group('col_1');
$criteria->limit(10);
$result = TableName::model()->findAll($criteria);
Can somebody guide me as I am quite new to MongoDB and YiiMongoDbSuite.
Thanks in advance,
Well to do it using MongoYii (which I maintain):
$result = MongoModel::model()->aggregate(
array(
'$group' => array('_id' => 'col_1'),
'$limit' => 10
)
)
I am unsure how to do it with YiiMongoDbSuite, in fact there is no group command in its EMongoCriteria from what I see.

Categories