query with a field in several conditions in mongodb - php

I need to make a query like this:
db.subscribers.find({LISTID: 59, {$or: [{LANG: {$in: ['English', 'Spanish']} },
{LANG: {$nin: ['Russian']} }]} });
It's supposed to get all subscribers from listid 59, who know English or Spanish or(and) doesn't know Russian. Instead of language there could be any field that can have multiple values.
It looks like this query works in mongodb console.
In this case one field can be in several conditions.
I there is the same field wouldn't be in several conditions, maybe it could be something like:
$collection->find(array('LISTID' => $listId,
array('$or' = array(LANG => array('$in' => array('English','Spanish')),
/*some other condition united with OR*/
)));
How to make this query in php?

It's supposed to get all subscribers from listid 59, who know English or Spanish and doesn't know Chinese.
If that's the objective of your query (I assume you mean "Russian" instead of "Chinese"), I don't see how your original console query works:
db.subscribers.find({
LISTID: 59,
{ $or: [
{ LANG: { $in: ["English", "Spanish"] } },
{ LANG: { $nin: ["Russian"] } }
] }
});
$or needn't be nested in its own object according to the documentation. Also, if you're looking for documents with a given LISTID that know two languages but not another, $and seems more appropriate:
db.subscribers.find({
LISTID: 59,
$and: [
{ LANG: { $in: ["English", "Spanish"] } },
{ LANG: { $ne: "Russian" } }
]
});
This would translate to PHP as:
$collection->find(array(
'LISTID' => $listId,
'$and' => array(
array('LANG' => array('$in' => array('English', 'Spanish'))),
array('LANG' => array('$ne' => 'Russian')),
),
));

I think the solution is something like this:
$number = $collection->find(array('LISTID' => $listId,
'$or' => array( array('LANG' => array('$in' => array('English', 'Spanish'))),
array('LANG' => array('$nin' => array('Russian'))),
) ))->count();

// Find record according to specific column
$getfollower = $dbnew1->find(array('follower' => $follower),
array('page_name' => 1, 'id'=>1, '_id'=>0));

Related

Insert array into another array based on if command - putting it in wrong place

I have this array:
$arr = array(
'reportDescription' => array(
'reportSuiteID' => 'globretailprod',
'elements' => array(
0 => array(
'id' => $queryElement
)
),
'metrics' => array(
0 => array(
'id' => $queryMetric
)
)
)
);
I'm trying to insert some code into the array using an if command. This is what I have:
if (isset($querySegment)) {
$arr['reportDescription']['segments'] = $querySegment;
}
However that gives me the wrong result, what I am trying to achieve is this:
{
"reportDescription": {
"reportSuiteID": "rbsglobretailprod",
"dateFrom": "2018-09-09",
"dateTo": "2018-09-10",
"dateGranularity": "day",
"metrics": [{
"id": "pageviews"
}],
"elements": [{
"id": "page"
}],
"segments": [{
"id": "jjj"
}]
}
}
Notice there are two issues with this. Firstly, segments isn't isn't insert with an id, it's just inserted as a value. Secondly, I am a bit concerned about the trailing comma after metrics in my original array, since I need to be able to add a comma after the metrics array if I do include segments.
Just use the same format as you use for the other items to get the same structure...
if (isset($querySegment)) {
$arr['reportDescription']['segments'] = array(
0 => array(
'id' => $querySegment
)
);
}
As for the comma, this should be added automatically as needed if your using json_encode()

Algolia conditional search

I have in my Algolia engine the next "entity"
Professional
objectID: "eyJpZCI6OX0="
...
status: id: 1
And I like to make a search just with the ones that have status = 1.
I've tried this:
$searchResult = $this->get('algolia.indexer')->rawSearch(Professional, $data, [
'hitsPerPage' => 10,
'page' => 1,
'facetFilters' => 'status:1',
]);
Seems that im nos using facetFilters correctly,
any help?
Thanks
From what I can see you have sub-attribute id inside the status attribute. So your record looks something like this:
{
"objectID": "eyJpZCI6OX0=",
...
"status": {
"id": 1
}
}
Correct?
In this case you need to specify the sub-attribute in your facetFilters as well. In your case it would look like this:
$searchResult = $this->get('algolia.indexer')->rawSearch(Professional, $data, [
'hitsPerPage' => 10,
'page' => 1,
'facetFilters' => 'status.id:1',
]);
If you use Algolia PHP API client, the code would look like this:
$client = new \AlgoliaSearch\Client('foo', 'bar');
$index = $client->initIndex('index_name');
$res = $index->search('', ['filters' => 'status.id:1']);
You can also replace facetFilters parameter by filters parameter, which is more powerful and allows you to specify more complex conditions.

Complex statement in MongoDB AND & OR conditions

Continuing on my project, I need to translate some SQL statements to mongoDB
My SQL Statement is:
Delete from 'table' where proc_id = $xxx and (day_id < $day OR day_id > $anotherDay)
Now my condition array is this:
$condicion = array(
'proc_id' => $xxx,
'$or' => array(
'day_id' => array(
'$lt' => $day,
'$gt' => $anotherDay
)
)
);
The function made for delete in mongo collections returns cannot delete...
Some help please?
Each "day_id" would be in it's own $or argument:
$query = array(
'proc_id' = > $xxx,
'$or' => array(
array( 'day_id' => array ( '$lt' => $day ) ),
array( 'day_id' => array ( '$gt' => $anotherDay ) ),
)
)
That is how $or conditions work as a "list" of possible expressions.
The JSON syntax is clearer to visualise:
{
"proc_id": $xxx,
"$or": [
{ "day_id": { "$lt": $day } },
{ "day_id": { "$gt": $anotherDay }}
]
}
Since there is a very clear distinction between a "list" and an "object" definition. $or conditions are "lists" of "objects", and that means you list the full condition just as if it were a query in itself. Since this is not called within an $elemMatch.
And of course the "DELETE" part is the .remove() method:
$collection->remove($query)
There are general examples and resources in the core documentation SQL to MongoDB Mapping Chart, where if the examples there do not immediately help, the linked articles and presentations should.

Map Reduce in Mongo, Convert mongo query to php mongo

I had a query in mongo which looks like
db.Table_Name.group({
"key": { "Camp": true },
"initial": { "Clicks": 0 },
"reduce": function(obj, prev) {
prev.Clicks = prev.Clicks + obj.Clicks-0;
},
"cond": { "Date": { $gte: "2012-10-26", $lte: "2012-10-28" } }
});
I want to use this code in php. I tried all the possible ways. Can any one help me out from this problem. Even I followed this http://php.net/manual/en/mongodb.command.php Please any one help me out.
I tried this
$reduce = new MongoCode(
"function(obj, prev) {prev.Clicks = prev.Clicks + obj.Clicks-0;}"
);
$result = $db_1->command(array(
'mapreduce' => 'Collection_Name',
'key' => array("Camp" => true),
'initial' => array('Clicks' => 0),
'reduce' => $reduce,
'cond' => array(
'Date' => array('$gte' => '2010-07-12' , '$lte' => '2013-07-12')
),
));
Have you tried using MongoCollection::group? For your example, it might look something like this (not tested).
$keys = array("Camp" => 1);
$initial = array("Clicks" => 0);
$reduce = "function(obj, prev) {prev.Clicks = prev.Clicks + obj.Clicks-0;}";
$condition = array(
'Date' => array('$gte' => '2010-07-12', '$lte' => '2013-07-12')
);
$result = $collection->group($keys, $initial, $reduce, $condition);
Also, you should try to embrace the MongoDB terminology, i know it's just an example, but Table_Name should be Collection_Name as MongoDb does not have tables.
You could use the group command here but it is:
Slow
Basically a Map Reduce
JavaScript
Normally does not work with sharding (some people have made it)
Is deprecated in favour of the aggregation framework
Instead a better option would be to use the aggregation framework:
$mongo->db->collection->aggregate(array(
array('$match'=>array('date'=>array('$gte' => '2010-07-12','$lte' => '2013-07-12'))),
array('$group'=>array('_id'=>'$Camp', 'sum_clicks'=>array('$sum'=>'$Clicks')))
));

mongodb: finding the highest numeric value of a column

I have MongoDB collection of documents containing several fields. One of the columns/fields should be numeric only, but some of these fields contain non-numerical (corrupt) data as string values. I should find the highest numerical value of this column, excluding the corrupt, non-numerical data. I am aware of the question Getting the highest value of a column in MongoDB, but AFAIK, this extended case was not covered.
The example below depicts the issue. For the highest value, the document with "age": 70 should be returned:
[
{
"id": "aa001",
"age": "90"
},
{
"id": "bb002",
"age": 70
},
{
"id": "cc003",
"age": 20,
}
]
Providing a PHP example for the find() / findOne() query would be of much help. Thanks a lot!
JohnnyHK came up with the perfect solution. Here's the working PHP code:
$cursor = $collection->find(array('age' => array('$not' => array('$type' => 2))), array('age' => 1));
$cursor->sort(array('age' => -1))->limit(1);
You can use the $type operator with $not in your query to exclude docs where age is a string. In the shell your query would look like:
db.test.find({age: {$not: {$type: 2}}}).sort({age: -1}).limit(1)
Or in PHP from Martti:
$cursor = $collection->find(array('age' => array('$not' => array('$type' => 2))), array('age' => 1));
$cursor->sort(array('price' => -1))->limit(1);
with PHP driver (mongodb)
using findOne()
$filter=[];
$options = ['sort' => ['age' => -1]]; // -1 is for DESC
$result = $collection->findOne(filter, $options);
$maxAge = $result['age']
You can use aggregate function to get maximum number from collections like this.
$data=$collection->aggregate(array
( '$group'=>
array('_id'=>'',
'age'=>array('$max'=>'$age'.)
)
)
);
This works for me
$options = ['limit' => 100,'skip' => 0, 'projection' => ['score' => ['$meta' => 'textScore']], 'sort' => ['score' => ['$meta' => 'textScore']]];

Categories