How do I extract subdocument in laravel mongodb - php

Hello Good Developers,
I am using jenssegers/laravel-mongodb package to query my MongoDB from Laravel.
Here's Fiddle for my query: https://mongoplayground.net/p/qzbNN8Siy-3
I have following JSON
[{
"id": "GLOBAL_EDUCATION",
"general_name": "GLOBAL_EDUCATION",
"display_name": "GLOBAL_EDUCATION",
"profile_section_id": 0,
"translated": [
{
"con_lang": "US-EN",
"country_code": "US",
"language_code": "EN",
"text": "What is the highest level of education you have completed?",
"hint": null
},
{
"con_lang": "US-ES",
"country_code": "US",
"language_code": "ES",
"text": "\u00bfCu\u00e1l es su nivel de educaci\u00f3n?",
"hint": null
}...
{
....
}
]
I am trying to run following command
db.collection.find({ 'id': "GLOBAL_EDUCATION" },{_id:0, id:1, general_name:1, translated:{ $elemMatch: {con_lang: "US-EN"} }})
Expecting result like this
[
{
"general_name": "GLOBAL_EDUCATION",
"id": "GLOBAL_EDUCATION",
"translated": [
{
"con_lang": "US-EN",
"country_code": "US",
"hint": null,
"language_code": "EN",
"text": "What is the highest level of education you have completed?"
}
]
}
]
Everything is fine while query directly in MoDB but issue arise when I am trying this in Laravel.
I've tried every possible known function from MongoDB package. but Not able to do this.
here's my Array
$findArray = [
[
'id' => "GLOBAL_EDUCATION",
],
[
'_id' => 0,
'id' => 1,
'general_name' => 1,
'translated' => [
'$elemMatch' => ['con_lang' => "US-EN"]
],
]
];
$model = GlobalQuestions::raw()->find($findArray) //OR
$data = GlobalQuestions::raw(function($collection) use ($findArray){
return $collection->find($findArray);
});
What I am doing wrong here, is this kind of Find() not possible here and I've to do this by aggregation?

Since no-one answered this, I am posting the solution if someone is having the same issue.
Doing some more R&D on the same I was able to do this using where and Project as well by Aggregation Pipelines.
----- Using Where() and Project() ------
$projectArray = [
'_id' => 0,
'id' => 1,
'general_name' => 1,
'translated' => [
'$elemMatch' => ['con_lang' => "FR-FR"]
],
];
$data = GlobalQuestions::where('id', '=', 'GLOBAL_EDUCATION')
->project($projectArray)
->get();
--- Using Aggregation and $unwind ---
$data = GlobalQuestions::raw(function($collection) {
return $collection->aggregate([
[
'$match' => [
'id' => "GLOBAL_EDUCATION"
]
],
[
'$unwind' => '$translated',
],
[
'$match' => [
'translated.con_lang' => "US-EN"
]
],
[
'$project' => [
'_id'=> 0,
'id'=> 1,
'general_name' => 1,
'translated' => 1,
]
]
]);
})->first();

Related

How to search in elastic search in array of objects?

I have structure in my es doc like :
"urls": {
"de": [
{
"page_type": 3,
"language_id": 13,
"url": "some/watteninseln/"
},
{
"page_type": 5,
"language_id": 13,
"url": "none/watteninseln/"
}
],
"pt": [
{
"page_type": 3,
"language_id": 22,
"url": "some/west-frisian-islands/"
}
]
}
And I want to be able get this doc with params
url and language
so,
$query[] =
[
"bool" => [
"minimum_should_match" => 1,
"should" => [
[
"exists" => [
"field" => 'urls.' . $filters['lang']. $filters['url']
]
],
]
]
];
Im trying like this, but it will be work if we have associative in key urls. But I need to find value in array of objects
Could someone tell me correct way to do it ?

Count and sum the array lengths of child arrays nested in documents - MongoDB / PHP

I have MongoDB documents like this:
{
"_id": "object1",
"type": "this_type",
"child_array": [
{...other fields here...},
{...other fields here...},
{...other fields here...}
],
"some_other_key": "some_value"
},
{
"_id": "object2",
"type": "this_type",
"child_array": [
{...other fields here...},
{...other fields here...}
],
"some_other_key": "some_value"
},
{
"_id": "object3",
"type": "this_type",
"child_array": [
{...other fields here...},
{...other fields here...},
{...other fields here...},
{...other fields here...}
],
"some_other_key": "some_value"
}
Is it possible to count how many nested children the child_arrays have?
I am currently using this, but it returns 3, because 3 documents have the child_array.
$collection = $mongodb->my_collection;
$nested_count_filter = [ "type" => "this_type", "child_array" => ['$exists' => true] ];
$nested_count = $collection->count($nested_count_filter);
I need it to return 9 for this example, as the first doc has 3, the second has 2, and the 3rd has 4, totaling 9 nested children.
Is there a MongoDB way to do this, or do I have to do this manually (eg, for loops)?
UPDATE - Solution
I tried:
$mongo_count = $collection.aggregate([
[ '$match' => [ 'type' => 'this_type' ] ],
[ '$group' => [
'_id' => null,
'child_array' => [ '$sum' => [ '$size'=> '$child_array' ]]
]]
]);
To get the actual counts, after using the method in the accepted answer, the Mongo cursor object has to be converted to an array:
$count_array = iterator_to_array($mongo_count);
$count = $count_array[0]['child_array'];
You need to use $group with null and $sum the $size of the child_array array
$collection.aggregate([
[ '$match' => [ 'type' => 'this_type' ] ],
[ '$group' => [
'_id' => null,
'child_array' => [ '$sum' => [ '$size'=> '$child_array' ]]
]]
])
which is similar to javascript
db.collection.aggregate([
{ "$match": { "type": "this_type" }},
{ "$group": {
"_id": null,
"child_array": { "$sum": { "$size": "$child_array" }}
}}
])

Elasticseach doesn't map all given fields [PHP]

I'm working with Elasticsearch-PHP client. I want to index my datas, but I have a problem with mapping. There is a problem: I create my data array, everything works fine, but when I add this array to my index body => my_data_array some datas show up, but not all of them. I don't know why. I just digged and try all of following steps but nothing changed.
I just attached my snippets.
This my controller file where I index datas:
{
$params = ['body' => []];
foreach($all_ads as $key => $ads){
$params['body'][] = [
'index' => [
'_index' => 'demo_data',
'_type' => 'demo',
'_id' => $ads->id
]
];
$params['body'][] = $ads->indexParams();
}
$responses = $client->bulk($params);
this is result json object:
"response": [
{
"id": 85345,
"old_id": "5088063",
"user_id": "2706",
"category_id": "15",
"type": "3",
"title": array[3],
"slug": "",
"sub_region_id": "8",
"condition": "1",
"username": "John Doe",
"price": "82000",
"price_type": "1",
"no_phone": "0",
"views": "29",
"hot": "0",
"vip": "0",
"price_measure": "0"
}
I have a datafield and it is not visible here.
Its data mapping structure
'data' => [
'type' => 'object',
'properties' => [
'key_id' => ['type' => 'integer'],
'value_id' => ['type' => 'integer'],
'key' => ['type' => 'keyword'],
'value' => ['type' => 'keyword']
]
]
How can I fix it?
I just check some question from here and github issue forum but nothing helps. Thanks!
You have to follow solution of the question. Its maybe helpful for you.
Elasticsearch mapping not working as expected
Ask Question

Using "aggregate" to combine a list of all subdocuments that match query?

I'm trying to use a PHP mongo library to "aggregate" on a data structure like this:
{
"_id": 100,
"name": "Joe",
"pets":[
{
"name": "Kill me",
"animal": "Frog"
},
{
"name": "Petrov",
"animal": "Cat"
},
{
"name": "Joe",
"animal": "Frog"
}
]
},
{
"_id": 101,
"name": "Jane",
"pets":[
{
"name": "James",
"animal": "Hedgehog"
},
{
"name": "Franklin",
"animal": "Frog"
}
}
For example, if I want to get all subdocuments where the animal is a frog. Note that I do NOT want all matching "super-documents" (i.e. the ones with _id). I want to get an ARRAY that looks like this:
[
{
"name": "Kill me",
"animal": "Frog"
},
{
"name": "Joe",
"animal": "Frog"
},
{
"name": "Franklin",
"animal": "Frog"
}
]
What syntax am I supposed to use (in PHP) to accomplish this? I know it has to do with aggregate, but I couldn't find anything that matches this specific scenario.
You can use below aggregation. $match to find documents where array has a value of Frog and $unwind the pets array. $match where document has Frog and final step is to group the matching documents into array.
<?php
$mongo = new MongoDB\Driver\Manager("mongodb://localhost:27017");
$pipeline =
[
[
'$match' =>
[
'pets.animal' => 'Frog',
],
],
[
'$unwind' =>'$pets',
],
[
'$match' =>
[
'pets.animal' => 'Frog',
],
],
[
'$group' =>
[
'_id' => null,
'animals' => ['$push' => '$pets'],
],
],
];
$command = new \MongoDB\Driver\Command([
'aggregate' => 'insert_collection_name',
'pipeline' => $pipeline
]);
$cursor = $mongo->executeCommand('insert_db_name', $command);
foreach($cursor as $key => $document) {
//do something
}
?>

Ingest Search (Elastic Search) is not working in PHP

I have installed elastic search and also install ingest plugin in my local server. Elastic engine is running nicely. I set up the following tasks:
mapping
indexing
Now I am stuck in searching, it's not working. It returns null array. Here is my code in PHP:
public function ingest_processor_searching($query)
{
$client = $this->client;
$params = [
'index' => 'ingest_index',
'type' => 'attachment',
'body' => [
'query' => [
'match' => [
'textField' => $query,
]
],
],
];
$response = $client->search($params);
return $response;
}
Result:
{
"took": 7,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 0,
"max_score": null,
"hits": []
}
}
But I have Data for the GET http://localhost:9200/ingest_index/attachment/2
{
"_index": "ingest_index",
"_type": "attachment",
"_id": "2",
"_version": 1,
"found": true,
"_source": {
"file_path": "/Users/selimreza/Sites/haber_dev/public/uploads/files/bower.txt",
"attachment": {
"content_type": "text/plain; charset=ISO-8859-1",
"language": "en",
"content": "Welcome to Dhaka",
"content_length": 18
},
"textField": "V2VsY29tZSB0byBEaGFrYQo="
}
}
What is the mistake I did?
Try removing the , from your 'textField' => $query since you aren't matching multiple values. If it still doesn't work, try using the term query instead of match:
$params = [
'index' => 'ingest_index',
'type' => 'attachment',
'body' => [
'query' => [
'term' => [ <-- have this
'textField' => $query <-- try removing the comma
]
],
],
];

Categories