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 ?
Related
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();
I am needing to ignore the apostrophe with indexed results so that searching for "Johns potato" will show results for "John's potato"
I was able to get the analyzer accepted but now I return no search results. Does anyone see something obvious that I am missing?
$params = [
'index' => $index,
'body' => [
'settings' => [
'number_of_shards' => 5,
'number_of_replicas' => 2,
'analysis' => [
"analyzer" => [
"my_analyzer" => [
"tokenizer" => "keyword",
"char_filter" => [
"my_char_filter"
]
]
],
"char_filter" => [
"my_char_filter" => [
"type" => "mapping",
"mappings" => [
"' => "
]
]
]
]
],
'mappings' => [
$type => [
'_source' => [
'enabled' => true
],
'properties' => [
'title' => [
'type' => 'text',
'analyzer' => 'my_analyzer'
],
'content' => [
'type' => 'text',
'analyzer' => 'my_analyzer'
]
]
]
]
]
];
I did find out that removing the analyzer from my field mappings allowed results to reappear, but I get no results the second I add the analyzer.
Here's an example query that I make.
{
"body": {
"query": {
"bool": {
"must": {
"multi_match": {
"query": "apples",
"fields": [
"title",
"content"
]
}
},
"filter": {
"terms": {
"site_id": [
"1351",
"1349"
]
}
},
"must_not": [
{
"match": {
"visible": "false"
}
},
{
"match": {
"locked": "true"
}
}
]
}
}
}
}
Probably, what you really want, is to use the english analyzer that is provided. The standard analyzer which is the default will tokenize on whitespace and some punctuation, but will leave apostrophes alone. The english analyzer can stem and remove stop words since the language is known.
Here is the standard analyzer's output, where you can see "john's":
POST _analyze
{
"analyzer": "standard",
"text": "John's potato"
}
{
"tokens": [
{
"token": "john's",
"start_offset": 0,
"end_offset": 6,
"type": "<ALPHANUM>",
"position": 0
},
{
"token": "potato",
"start_offset": 7,
"end_offset": 13,
"type": "<ALPHANUM>",
"position": 1
}
]
}
And here is the english analyzer where you can see the 's is removed. The stemming will allow "John's", "Johns", and "John" to all match the document.
POST _analyze
{
"analyzer": "english",
"text": "John's potato"
}
{
"tokens": [
{
"token": "john",
"start_offset": 0,
"end_offset": 6,
"type": "<ALPHANUM>",
"position": 0
},
{
"token": "potato",
"start_offset": 7,
"end_offset": 13,
"type": "<ALPHANUM>",
"position": 1
}
]
}
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
}
?>
Sample records in the collection,
(doc 1)
[{
"_id": ObjectId("567941aaf0058ed6755ab3dc"),
"hash_count": NumberInt(7),
"time": [
NumberInt(1450787170),
NumberInt(1450787292),
NumberInt(1450787307),
NumberInt(1450787333),
NumberInt(1450787615)
],
"word": "batman"
},
(doc 2)
{
"_id": ObjectId("567941aaf0058ed6755ab3dc"),
"hash_count": NumberInt(7),
"time": [
NumberInt(1450787170),
NumberInt(1450787292),
NumberInt(1450787307),
NumberInt(1450787333),
NumberInt(1450787354),
NumberInt(1450787526),
NumberInt(1450787615)
],
"word": "apple"
}]
Have stored using PHP,
I want to find the number of records in between time (1450787307) and (1450787615)
Answer:
apple=5
batman=3
What should be query for it?
I ran this command
{
aggregate : "hashtags",
pipeline:
[
{$match:{"time":{$gte:NumberInt(1450787307), $lte:NumberInt(1450787615)}}},
{$unwind:"$time"},
{$match:{"time":{$gte:NumberInt(1450787307), $lte:NumberInt(1450787615)}}},
{$group:{"_id":"$word","count":{$sum:1}}}
]
}
which gave this result
Response from server:
{
"result": [
],
"ok": 1
}
Since you are stuck with an older version of mongoDB, you cannot leverage the power of the array aggregation operators introduced in 3.2.
You would have to aggregate as below:
db.collection.aggregate([
{$match:{"time":{$gte:NumberInt(1450787307), $lte:NumberInt(1450787615)}}},
{$unwind:"$time"},
{$match:{"time":{$gte:NumberInt(1450787307), $lte:NumberInt(1450787615)}}},
{$group:{"_id":"$word","count":{$sum:1}}}
])
translated to PHP,
$result = $c->aggregate([
[ '$match' => [ 'time' => [ '$gte' => NumberInt(1450787307),
'$lte' => NumberInt(1450787615) ] ] ],
[ '$unwind' => '$time' ],
[ '$match' => [ 'time' => [ '$gte' => NumberInt(1450787307),
'$lte' => NumberInt(1450787615) ] ] ],
[ '$group' => [ '_id' => '$word', 'count' => [ '$sum' => 1 ] ] ]
]);
In version 3.2, you could use the combination of $filter and $size to acheive the same result and with less expensive operations.
db.collection.aggregate([
{$match:{"time":{$gte:NumberInt(1450787307),
$lte:NumberInt(1450787615)}}},
{$project:{"_id":0,"word":1,
"count":{$size:{$filter:
{"input":"$time",
"as":"t",
"cond":{$and:[
{$gte:["$$t",NumberInt(1450787307)]},
{$lte:["$$t",NumberInt(1450787615)]}]}
}
}
}
}}
])
ok , after trying a lot I have come with this answer and is correct
for
1450787615- lower limit
1450855155- upper limit
db.hashtags.aggregate([
{
"$match": {
"time": {
"$gte": 1450787615, "$lte": 1450855155
}
}
},
{ "$unwind": "$time" },
{
"$match": {
"time": {
"$gte": 1450787615, "$lte": 1450855155
}
}
},
{
"$group": {
"_id": "$word",
"count": {
"$sum": 1
}
}
}
])
answer is like
{
"result" : [
{
"_id" : "batman",
"count" : 3
},
{
"_id" : "dear",
"count" : 1
},
{
"_id" : "ghost",
"count" : 1
}
],
"ok" : 1
}
db.collection.find({time:{$gt: 1450787307, $lt: 1450787615}});
This will first give you a cursor of all docs that fit within your given time range. Once you have that you can iterate through the cursor and print out the name as well as some loop logic to find the number of occurences for each one. I've only lightly worked with mongodb so there may be a more efficient way to do this.
reference:
https://docs.mongodb.org/v3.0/reference/method/db.collection.find/
i am trying to sort some data, where in my base skeleton my sorting is not working and if i remove the sorting it works fine.
So how can i put sorting in my base skeleton and sort some data.
i can't put just
$params['body'] = [
'sort' => [['title' => ['order' => 'asc']]]];
$results = $client->search($params);
Because i have other condition where i need the must condition.
Can anyone knows how it can be solve.
Any advice will be really appreciate.
// my base skeleton
$params = array(
'index' => "myIndex",
'type' => "myType",
'body' => array(
'query' => array(
'bool' => array(
'must' => array(
// empty should clause for starters
)
)
),
'sort' => array()
)
);
// sorting is not working with bool and must
if ($request->request->get('salarySort')) {
$params['body']['query']['bool']['must'][] = array(
'sort' => array(
"title" => array('order' => 'asc')
)
);
}
this is what i get as a json_encode ---
{
"took": 4,
"timed_out": false,
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"hits": {
"total": 1066,
"max_score": null,
"hits": [
{
"_index": "myIndex",
"_type": "myType",
"_id": "pe065319de73937aa6ef46413afd7aac26a58a611",
"_score": null,
"_source": {
"title": "Smarason trycker ",
"content": "HIF gör 2-0 mot Halmstad.",
"tag": [
"Soprts"
],
"category": [
"Sports"
]
},
"sort": [
"0"
]
},
{
"_index": "myIndex",
"_type": "myType",
"_id": "pebc44a70008f53f74f23ab23f8a1f79b2b729448",
"_score": null,
"_source": {
"title": "Anders Svenssons tips gav 1-0",
"content": "Anders Svenssons tips i halvtid Kalmar FF.",
"source": "Unknown",
"tag": [
"Soprts"
],
"category": [
"Sports"
]
},
"sort": [
"0"
]
}
]
}
}
query in JSON ---
{
"index": "myIndex",
"type": "myType",
"size": 30,
"body": {
"query": {
"match_all": []
},
"sort": [
{
"title": "asc"
}
]
}
}
You're almost there. You've correctly placed the empty sort array at the same level as your query, which is correct.
The issue comes later when you try to feed it as a bool/must constraint instead of in the empty sort array.
// sorting is not working with bool and must
if ($request->request->get('salarySort')) {
$params['body']['sort'][] = array( <---- this line needs to be changed
"Salary" => 'asc' <---- this line needs to be changed, too
);
}