mongo->php, querying inside embeded objects - php

I have this structure:
"_id": NumberInt(1),
"link_id": {
"1000748": {
"pi": NumberInt(34),
"li": NumberInt(8)
},
"1002836": {
"pi": NumberInt(21),
"li": NumberInt(1002836)
}
}
I want to make a query to select only the link_ids with a 'pi' => 34. I have tried in php $res = $collection->findOne(array("_id" => intval($_catids['categoryid'])), array("linkid.$.pi" => intval(34)));
No success. Any ideas? Thx a lot!

First off I recommend to use the MongoId object for the _id field, has a lot of options and a lot of usefull functions within it
But that did not answer the question, the query is as followed
{
"linked_id.pi": 34
}
Then you translated to PHP it is
array(
'linked_id.pi' => 34,
)
Then depening on the result you want you need to use find or findOne

Related

Laravel - pluck with specified keys

I have a line of code similar to the following:
Sport::pluck('id', 'name)
I am dealing with frontend JavaScript that expects a list in this format:
var list = [
{ text: 'Football', value: 1 },
{ text: 'Basketball', value: 2 },
{ text: 'Volleyball', value: 3 }
...
]
I am trying to figure out how I can somehow transform the id and name values that I pluck from my model to a format similar to the Javascript list.
If that's unclear, I am looking to end up with an associative array that contains two keys: text and value, where text represents the name field on my model, and where value represents the id of the model - I hope this makes sense.
How would I approach this?
I initially tried something like this (without checking the documentation)
Sport::pluck(["id" => "value", "name" => "text]);
But that isn't how you do it, which is quite clear now. I've also tried some map-related snippet, which I cannot seem to Ctrl-z to.
Any suggestions?
Another method is to use map->only():
Sport::all()->map->only('id', 'name');
The purpose of pluck is not what you intend to do,
Please have a look at below examples,
Sport::selectRaw("id as value, name as text")->pluck("text","value");
// ['1' => 'Football', '2'=>'BasketBall','3'=>'Volleyball',...]
Syntax
$plucked = $collection->pluck('name', 'product_id');
// ['prod-100' => 'Desk', 'prod-200' => 'Chair']
Please see the documentation.
Your output is possible using simple code.
Sport::selectRaw('id as value, name as text')->get();
You could use map.(https://laravel.com/docs/5.8/collections#method-map)
$mapped = Sport::all()->map(function($item, $index) {
return [
"id" => $item["id"],
"name" => $item["text"]
];
});
This is the easiest way. Actually Laravel offers a better way for it. You can use api resources to transform your data from eloquent for the frontend:
https://laravel.com/docs/5.8/eloquent-resources
Try with toArray function:
Sport::pluck('id', 'name)->toArray();
Then you can return your result with json_encode php function;

how to remove duplicate entry from array objet

Morning I'm working on a project and I have a issue, it's about to know how to remove duplicate entry from an array object .
Here is structure of my array :
"IDGROUP": [
{
"id": 72
},
{
"id": 72
}
]
Here is code snippet:
if($compteGroupes && $compteGroupes->getId()!=0){
$Tableaux_pack[$current_id_fictif]["ingroup"]]=
$Mes_comptes_reels_dependants [$taille_reel];
$Tableaux_pack[$current_id_fictif]["IDGROUP"]=
array(
'id'=>$compteGroupes->getId()
);
}
thank's for your help
Your object looks like a javascript object - what do you actually mean?
are the entries classes? are they arrays
do you want to filter nested/multidimensional arrays based on their values?
do you want to filter different class objects?
see here: https://stackoverflow.com/a/2426579/8548024

how to query group by and distinct with a limit in MongoDB PHP codeigniter?

Is such a operation possible?
sample record:
{
_id: ObjectId("51d6be147483c58419000002"),
user: "ashok",
action: "login",
time: 1373027860,
details: {
user_entries: "blah..blah",
url: "web.domain.com"
}
}
Suppose, i want to group by url visited, for each user,
group by url where user = "ashok", limit 10.
I am using AlexBilbie library for MongoDB-Codeigniter (it doesnt have aggregation). so using plain php.
Still even if I could aggregate, how to distinct or limit it?
Any suggestion is welcome.
First of all using group_by and distinct together doesn't make any sense. Either you are using group_by or distinct.
If you want to do some kind of pagination for a grouped query you have to use map and reduce or the aggregation pipeline. In your case the aggregation would look like that.
db.users.aggregate(
{ '$match' => { 'user' => 'ashok' } },
{ '$group' => { '_id' => '$details.url' } },
{ '$skip' => 0 },
{ '$limit' => 10 }
)
I am using this aggregation feature to display references at VersionEye. The aggregation feature allows to do grouping and paging on db level, that's why it's much faster then other ORM or pagination solutions.
In the below format you can give a limit:
$this->mongo_db->order_by(array('Student_Name'=>'asc'))->limit(20)->get('mycollection_name');

Query mongodb with php-mongo

I am building a simple messaging system, and i have a collection in mongodb with documents like this:
{ "_id" : ObjectId("50ad003f9811e5bc5c000000"), "between" : [ "user1,user2,user3" ] }
I want to perform this query:
db.conversations.find({'between': ["user1,user2,user3"]});
to get this exact document back. This query works in mongo shell.
in php-mongo, i tried this:
$collection->find(array("between"=>array("user1", "user2", "user3")));
but it does not work.
What am i doing wrong ?
Wouldn't you want to do an In query here?
db.collection.find( { "between" : { $in : ["user1", "user2", "user3"] } } );
See In query here:
Mongo Advanced $in query
making your PHP query look like:
$collection->find(array("between"=>array("$in"=>array("user1", "user2", "user3"))));
//untested, should be something similar to this.
or if you're trying to find it exactly wouldn't you just be able to do:
$collection->find(array("between"=>array("user1,user2,user3")));
First of all when you are saving your data you have to use array not a string
{ "between" : [ "user1,user2,user3" ] }
this stores in "between" an array of one element "user1,user2,user3"
Basically when you do your query in shell everything is ok, because you are asking for a array with one element. But in php you are asking for an array of three elements.
So, when you save your data, most probably that is what you need :
{ "between" : [ "user1","user2","user3" ] }
and this will give you an array of three users.
Then read the documentation http://www.mongodb.org/display/DOCS/Advanced+Queries to and adjust your query depends on what you need: either the exact array or only some elements in the array
Have you tried:
$collection->find(array("between"=>"user1,user2,user3"));
or
$collection->find(array( "$elemMatch" => array( "between"=>"user1,user2,user3" ));
The $in operator is analogous to the SQL IN modifier, allowing you to specify an array of possible matches.
Consider the following example which uses the $or operator.
$collection->find([
'select' => ['$in' => ['option 1', 'option 2', 'option 3']]
]);
References

Map Reduce To Get Most popular tags

I have a problem that I need some help on but I feel I'm close. It involves Lithium and MongoDB Code looks like this:
http://pastium.org/view/0403d3e4f560e3f790b32053c71d0f2b
$db = PopularTags::connection();
$map = new \MongoCode("function() {
if (!this.saved_terms) {
return;
}
for (index in this.saved_terms) {
emit(this.saved_terms[index], 1);
}
}");
$reduce = new \MongoCode("function(previous, current) {
var count = 0;
for (index in current) {
count += current[index];
}
return count;
}");
$metrics = $db->connection->command(array(
'mapreduce' => 'users',
'map' => $map,
'reduce' => $reduce,
'out' => 'terms'
));
$cursor = $db->connection->selectCollection($metrics['result'])->find()->limit(1);
print_r($cursor);
/**
User Data In Mongo
{
"_id" : ObjectId("4e789f954c734cc95b000012"),
"email" : "example#bob.com",
"saved_terms" : [
null,
[
"technology",
" apple",
" iphone"
],
[
"apple",
" water",
" beryy"
]
] }
**/
I am having a user savings terms they search on and then I am try to get the most populars terms
but I keep getting errors like :Uncaught exception 'Exception' with message 'MongoDB::__construct( invalid name '. does anyone have any idea how to do this or some direction?
First off I would not store this in the user object. MongoDb objects have an upper limit of 4/16MB (depending on version). Now this limit is normally not a problem, but when logging inline in one object you might be able to reach it. However a more real problem is that every time you need to act on these objects you need to load them into RAM and it becomes consuming. I dont think you want that on your user objects.
Secondly arrays in objects are not sortable and have other limitations that might come back to bite you later.
But, if you want to have it like this (low volume of searches should not be a problem really) you can solve this most easy by using a group query.
A group query is pretty much like a group query in sql, so its a slight trick as you need to group on something most objects share. (An active field on users maybe).
So, heres a working group example that will sum words used based on your structure.
Just put this method in your model and do MyModel::searchTermUsage() to get a Document object back.
public static function searchTermUsage() {
$reduce = 'function(obj, prev) {
obj.terms.forEach(function(terms) {
terms.forEach(function(term) {
if (!(term in prev)) prev[term] = 0;
prev[term]++;
});
});
}';
return static::all(array(
'initial' => new \stdclass,
'reduce' => $reduce,
'group' => 'common-value-key' // Change this
));
}
There is no protection against non-array types in the terms field (you had a null value in your example). I removed it for simplicity, its better to probably strip this before it ends up in the database.

Categories