Using mongodb's $and in php - php

Setup, php + mongodb.
The database should contain multiple items where 'Title' contains both 'Apple' and 'Orange'. I am trying to obtain only the items that contain BOTH 'Apple' and 'Orange'.
$regexOne = new MongoRegex( '/Apple/i' );
$regexTwo = new MongoRegex('/Orange/i');
$cursor = $collection->find( array( '$and' => array( array('Title' => $regexOne), array('Title' => $regexTwo) ) ) );
The same query with the '$and' replaced with a '$or' works correctly (or at least appears to), but this returns nothing despite there being data in the database that matches these conditions.

Echoing what dimo414 said, the first step is simply comparing Mongo's shell to PHP. Both of these are equivalent:
$ mongo
MongoDB shell version: 2.2.0-rc0
connecting to: test
> db.foo.drop()
true
> db.foo.insert({title:"apple"})
> db.foo.insert({title:"orange"})
> db.foo.insert({title:"apple orange"})
> db.foo.insert({title:"banana apple"})
> db.foo.insert({title:"banana plum"})
> db.foo.find({$and: [{title:/apple/i}, {title:/orange/i}]})
{ "_id" : ObjectId("501804c4e7dc9abd7b58cd83"), "title" : "apple orange" }
> db.foo.find({$or: [{title:/apple/i}, {title:/orange/i}]})
{ "_id" : ObjectId("501804bde7dc9abd7b58cd81"), "title" : "apple" }
{ "_id" : ObjectId("501804c0e7dc9abd7b58cd82"), "title" : "orange" }
{ "_id" : ObjectId("501804c4e7dc9abd7b58cd83"), "title" : "apple orange" }
{ "_id" : ObjectId("501804cce7dc9abd7b58cd84"), "title" : "banana apple" }
And in PHP (using phpsh):
php> $c = (new Mongo())->test->foo;
php> =iterator_to_array($c->find(['$and' => [['title' => new MongoRegex('/apple/i')], ['title' => new MongoRegex('/orange/i')]]]))
array(
"501804c4e7dc9abd7b58cd83" => array(
"_id" => <object #10 of type MongoId> {
$id => "501804c4e7dc9abd7b58cd83",
},
"title" => "apple orange",
),
)
php> =iterator_to_array($c->find(['$or' => [['title' => new MongoRegex('/apple/i')], ['title' => new MongoRegex('/orange/i')]]]))
array(
"501804bde7dc9abd7b58cd81" => array(
"_id" => <object #11 of type MongoId> {
$id => "501804bde7dc9abd7b58cd81",
},
"title" => "apple",
),
"501804c0e7dc9abd7b58cd82" => array(
"_id" => <object #12 of type MongoId> {
$id => "501804c0e7dc9abd7b58cd82",
},
"title" => "orange",
),
"501804c4e7dc9abd7b58cd83" => array(
"_id" => <object #13 of type MongoId> {
$id => "501804c4e7dc9abd7b58cd83",
},
"title" => "apple orange",
),
"501804cce7dc9abd7b58cd84" => array(
"_id" => <object #14 of type MongoId> {
$id => "501804cce7dc9abd7b58cd84",
},
"title" => "banana apple",
),
)

Related

Remove specific string from multidimensional array by value, not key

I need to remove Jackie Jackson from this array, I tried unset(I do not want to use key), array_diff, array_search. Nothing is working for me.
$employeeList= array(
array(
"ID" => "ID",
"Name" => "Name",
"Surname" => "Surname",
),
array(
"ID" => 1,
"Name" => "John",
"Surname" => "Smith",
),
array(
"ID" => 2,
"Name" => "Jackie",
"Surname" => "Jackson",
),
array(
"ID" => 3,
"Name" => "Chris",
"Surname" => "Jones",
),
array(
"ID" =>4,
"Name" => "Amanda",
"Surname" => "Cullen",
),
array(
"ID" =>5,
"Name" => "Jeremy",
"Surname" => "Goodwin",
),
);
if you want to unset you can use the id of Jackie Jackson to match his key.
$id = 2;
unset($employeeList[array_search($id,array_column($employeeList, "ID"))]);
Have fun :)
Array filter to check if the name and surname match. The string must contain name and surname separated by a space in this case so we can "explode" and pick up each individually. If name or surname do not exist in the "name_to_exclude" the function will simply return the original array.
$name_to_exclude = "Jackie Jackson";
$exclude = explode(' ', $name_to_exclude);
$employeeList = array_filter($employeeList, function($val) use ($exclude) {
if(array_key_exists(0, $exclude) && array_key_exists(1, $exclude)) {
return $val['Name'] != $exclude[0] && $val['Surname'] != $exclude[1];
}
return true;
});

Return result of recursive function

I got a recursive function which currently echo the results. I want this function to return results and loop them with foreach inside markup.
I understand that i should use some kind of iteration for each array to get my desired result but have failed with that. Currently my code look like this(with attempts to iterate):
public static function recursiveChildCategory($categories = array(), $depth = 0, $i = 0) {
$ca = [];
// Loop through categories
foreach($categories as $key => $category){
echo str_repeat(" ", $depth);
echo "<a href='".implode('/', $category['breadcrumb'])."'>{$category['title']}</a>";
echo '<br>';
$ca[$i] = [
'id' => $category['id'],
'title' => $category['title'],
];
if(isset($category['child'])) {
// Loop
self::recursiveChildCategory($category['child'], $depth + 1, $i++);
}
}
return $ca;
}
And incoming array to the function:
Array (
[0] => Array (
[id] => 7
[title] => Deserts
[slug] => deserts
[child] => Array (
[0] => Array (
[id] => 8
[title] => Space
[slug] => space
[child] => Array (
[0] => Array (
[id] =>
[title] =>
[slug] =>
[child] => Array ( )
)
)
)
)
)
)
Currently it just returns first level of child categories "Deserts", but nothing about "Space".
As desired result i want function to return all categories with $depth and infinite path to multiple child categoires (to do the same work as currently echo doing).
Thanks in advice
Try this and tell me if it's what you are looking for :
The array for my test :
$array = [
0 => [
"id" => 7,
"title" => "Deserts",
"slug" => "deserts",
"child" => [
0 => [
"id" => 8,
"title" => "Space",
"slug" => "space",
"child" => [
0 => [
"id" => 9,
"title" => "Test",
"slug" => "test"
]
]
]
]
]
];
The recursive function :
function recursiveChildCategory($categories, $depth = 0, $ca = []) {
// Loop through categories
foreach($categories as $key => $category){
$ca[$depth] = [
'id' => $category['id'],
'title' => $category['title'],
];
if(isset($category['child'])) {
// Loop
$ca = recursiveChildCategory($category['child'], $depth + 1, $ca);
} else {
break;
}
}
return $ca;
}
Now, how to use it :
$test = recursiveChildCategory($array);
var_dump($test);
And this is the output :
array(3) {
[0]=>
array(2) {
["id"]=>
int(7)
["title"]=>
string(7) "Deserts"
}
[1]=>
array(2) {
["id"]=>
int(8)
["title"]=>
string(5) "Space"
}
[2]=>
array(2) {
["id"]=>
int(9)
["title"]=>
string(4) "Test"
}
}
Here is a link to test it : http://sandbox.onlinephpfunctions.com/
EDIT : I made some modification because in OP example array can have multiple result in first "depth", here is the "new" solution :
The array for test :
$array = [
"0" =>
[ "id" => 3, "title" => "Subcat", "slug" => "subcat", "child" =>
[ "0" =>
[ "id" => 5, "title" => "Subsubcat2", "slug" => "subcat2", "child" =>
[ "0" =>
[ "id" => "", "title" => "", "slug" =>"", "breadcrumb" => [ "0" => "homeworld", "1" => "cat", "2" => "subcat", "3" => "subcat2" ], "child" => [ ] ]
]
]
]
],
"1" =>
[ "id" => 4, "title" => "Kalahari", "slug" => "kalahari", "child" =>
[ "0" => [ "id" => 7, "title" => "deserts", "slug" => "deserts", "child" =>
[ "0" =>
[ "id" => 8, "title" => "Ural", "slug" => "ural", "child" =>
[ "0" => [ "id" =>"", "title" =>"", "slug" =>"", "child" => [ ] ] ]
]
]
]
]
]
];
The function : I just add $ca[$depth][] instead of $ca[$depth]
function recursiveChildCategory($categories, $depth = 0, $ca = []) {
// Loop through categories
foreach($categories as $key => $category){
$ca[$depth][] = [
'id' => $category['id'],
'title' => $category['title'],
];
if(isset($category['child'])) {
// Loop
$ca = recursiveChildCategory($category['child'], $depth + 1, $ca);
} else {
break;
}
}
return $ca;
}
And now the result :
$test = recursiveChildCategory($array);
foreach ($test as $depth => $c) {
echo "depth : ".$depth."\n";
foreach ($c as $result) {
echo "Title : ".$result['title']."\n";
}
echo "=============\n";
}
The output is :
depth : 0
Title : Subcat
Title : Kalahari
=============
depth : 1
Title : Subsubcat2
Title : deserts
=============
depth : 2
Title :
Title : Ural
=============
depth : 3
Title :
=============
Test here : link

How to find the average rating based on item name

I am working on building simple recommendation engine using PHP and MongoDB. I am trying to find the average rating of each item but I did not figure it out yet.
my collection is:
{
"_id" : 1,
"item" : "efg",
"rating" : 5.0,
"date" : ISODate("2014-01-01T08:00:00.000Z")
}
{
"_id" : 2,
"item" : "efg",
"rating" : 2.0,
"date" : ISODate("2014-01-01T08:00:00.000Z")
}
{
"_id" : 3,
"item" : "abc",
"rating" : 5.0,
"date" : ISODate("2014-01-01T08:00:00.000Z")
}
{
"_id" : 4,
"item" : "abc",
"rating" : 4.0,
"date" : ISODate("2014-01-01T08:00:00.000Z")
}
{
"_id" : 5,
"item" : "xyz",
"rating" : 3.0,
"date" : ISODate("2014-01-01T08:00:00.000Z")
}
This is the code I have tried recently:
$out = $sales->aggregate(
array(
'$group' => array(
'_id' => '$item',
'avgrating' => array('$avg' => '$rating')
)
)
);
var_dump($out);
Please try executing following code snippet
$out = $sales->aggregate(
array(
'$group' => array(
'_id' => array('item' => '$item'),
'avgrating' => array('$avg' => '$rating')
)
)
);
var_dump($out);
I got it working using this code:
$pipeline = array(
array(
'$group' => array(
'_id' => '$itemId',
'avgrating' => array('$avg' => '$rating'),
),
)
);
$out = $sales1->aggregate($pipeline);
var_dump($out)

PHP Mongodb create Text Index

I am new in MongoDB, and I'm trying to create a text index.
After trying several hours, I have not accomplished anything.
I have an array like this:
//The keys and values are reversed to avoid duplicates in the array keys.
$arr = array(
'Personal' => array(
'PEPE' => "_id",
'd' => array(
"full_name" => "Pedro",
"last_name" => "Picapiedras",
"address"=> "La matanza 123",
"department"=> "Soporte"
), //d end
'PABLO' => "_id",
'd' => array(
"full_name"=> "Pablo",
"last_name"=> "Marmolejo",
"address"=> "Pica 123",
"department"=> "Soporte"
), //d end
)//personal end
);//arr end
I want to create an Index of the _id field so that to edit or view documents, access them through "Pablo" or "Pepe".
Is this possible? Could you give me a hand on how I can do this?
Edit
I have tried with
db.reviews.createIndex( { comments: "text" } )
and
$user = Array(
'_id' => "$id",
'name' => $name,
);
$query = Array( '_id' => "$id" );
$query = Array( '_id' => new MongoId("$id") );
Try this:
$arr = array(
'PEPE' => array(
"_id" => 'PEPE',
'd' => array(
"full_name" => "Pedro",
"last_name" => "Picapiedras",
"address" => "La matanza 123",
"department" => "Soporte"
) //d end
), //PEPE END
'PABLO' => array(
"_id" => 'PABLO',
'd' => array(
"full_name" => "Pablo",
"last_name" => "Marmolejo",
"address" => "Pica 123",
"department" => "Soporte"
), //d end
) // Pablo END
); //$arr end
function insertMongo($array) {
try {
$mongo = new MongoClient();
$db = $mongo -> dbName;
$collection = $db -> collectionName;
$collection -> insert($array);
} catch (MongoCursorException $e) {
die("Query failed ".$e - > getMessage());
}
} //insertMongo
//To execute:
foreach($arr as $a) {
insertMongo($a);
};

MongoCollection group question

<?php
$collection->insert(array("category" => "fruit", "name" => "apple"));
$collection->insert(array("category" => "fruit", "name" => "peach"));
$collection->insert(array("category" => "fruit", "name" => "banana"));
$collection->insert(array("category" => "veggie", "name" => "corn"));
$collection->insert(array("category" => "veggie", "name" => "broccoli"));
$keys = array("category" => 1);
$initial = array("items" => array());
$reduce = "function (obj, prev) { prev.items.push(obj.name); }";
$g = $collection->group($keys, $initial, $reduce);
echo json_encode($g['retval']);
?>
not clear line $keys = array("category" => 1); why need write "category" => 1 instead of symply write "category" ?
why need write "category" => 1 instead of symply write "category" ?
The query engine for MongoDB used JSON objects. So everything is a key-value pair. The PHP driver is representing key-value pairs using hash tables (or dictionaries).
If you look at the aggregation documentation, it has the following example:
key: { a:true, b:true }
In PHP this would be represented as
$key: array('a' => 1, 'b' => 1)
I agree that the 1 seems unnecessary, but it's there to keep the JSON syntax valid.

Categories