Pagination in Elasticsearch PHP - php

I have an array in Elasticsearch which returns 400 records:
$result = $search->search($keyword);
echo "<pre>"; print_r($result); exit;
I'm running a foreach loop for $results to display. How can I add pagination of Elasticsearch?
below is code for search:
$params = [
'index' => $this->client->getIndex(),
'type' => $this->client->getType(),
"from" => 0, "size" => 100,
"scroll" => "1m",
'body' => [
"query" => [
"bool" => [
"must" => [
[
"multi_match" => [
"fields" => ["prod_name", "prod_seo_name"],
"type" => "phrase_prefix",
"query" => $query
]
],
[
"term"=> ["cat_type_id"=>1]
]
]
]
]
],
];
Querying in BD returns 400 records but elastic search giving 100 as I added size. How Do i scroll to another page?
my URl: http://example.com/ppm2.0/search.html?q=samsung

Related

How to use $in in array of embed array mongodb

I have photos_comments collection:
{
"_id" : ObjectId(""),
"photo_id" : ObjectId(""),
"content" : "Comment 1",
"is_approved" : "1",
"user" : {
"user_id" : ObjectId(""),
"name" : "",
"avatar" : ".jpg"
},
"likes" : [
{
"user_id" : ObjectId("")
}
],
"like_count" : 1,
"reply_count" : 5,
"replies" : [
{
"reply_id" : ObjectId(""),
"content" : "Reply 1",
"is_approved" : "1",
"user" : {
"user_id" : ObjectId(""),
"name" : "",
"avatar" : ".jpg"
},
"likes" : [
{
"user_id" : ObjectId("")
}
],
"like_count" : 1
},
]
}
I use $in to check if current user like reply comment:
$collection->aggregate(
[
[
'$match' => [
'_id' => new ObjectId($comment_id)
]
],
[
'$project' => [
'replies.reply_id' => 1,
'replies.like_count' => 1,
'replies.content' => 1,
'replies.is_liked' => ['$in' => [['user_id' => $user_id], '$replies.likes']],
'replies.user' => 1,
'replies.created_at' => 1
]
],
['$sort' => ["replies.reply_id" => 1]],
['$limit' => 5]
]);
But replies.is_liked alway return false, although it exist user_id in likes array from replies array embed.
How to fix it? Thanks!
It looks like your post is mostly code; please add some more details.
If you want to alter the array content to add a new field based on a condition, then you want the $map operator, and probably using $addFields if you don't want to restrict or change the rest of the document returned:
$collection->aggregate([
[ '$match' => [
'_id' => new ObjectId($comment_id)
]],
[ '$addFields' => [
'replies' => [
'$map' => [
'input' => '$replies',
'in' => [
'reply_id' => '$$this.reply_id',
'content' => '$$this.content',
'is_approved' => '$$this.is_approved',
'is_liked' => [ '$in' => [ $user_id, '$$this.likes.user_id' ] ],
'like_count' => '$$this.like_count'
]
]
]
]],
... # any other pipeline
])
Or using $mergeObjects if your MongoDB supports it and you prefer:
$collection->aggregate([
[ '$match' => [
'_id' => new ObjectId($comment_id)
]],
[ '$addFields' => [
'replies' => [
'$map' => [
'input' => '$replies',
'in' => [
'$mergeObjects' => [
'$$this',
[ 'is_liked' => [ '$in' => [ $user_id, '$$this.likes.user_id' ] ] ]
]
]
]
]
]],
... # any other pipeline
])
In both cases of course where $user_id is your PHP variable as the singular value in argument to $in, and where the '$$this.likes.user_id' is the MongoDB representation of the array of user_id values in that inner array. Note the array is the second argument and the singular is the first.
The $map operator uses the '$$this' to represent the current element of the array being processed. In both examples this allows re-mapping of the array content, just as the operator name implies.

Defining search rules in elasticsearch

How can I combine these two queries so I can search by name, publisher with one type of rules and ean by different set of rules, all in one query?
'must'=> [
[
"multi_match" => [
"query" => $this->builder->query,
"fields" => ['name', 'publisher', 'platform'],
"fuzziness" => 'auto',
"prefix_length" => 1,
],
"match" => [
"query" => $this->builder->query,
"fields" => ['ean'],
"prefix_length" => 1
],
]
]
I used this code to solve my problem
'should'=> [
[
"multi_match" => [
"query" => $this->builder->query,
"fields" => ['name', 'publisher', 'platform'],
"fuzziness" => 'auto',
"prefix_length" => 1,
'operator' => 'or'
],
],
[
"match" => [
"ean" => $this->builder->query,
],
]
]

How to pass null filter in elastic search + PHP

I want to filter search result. I want to search that if 'manuf_id' is not specified than is should return all records. below is my search query in elastic.
$params = [
'index' => $this->client->getIndex(),
'type' => $this->client->getType(),
"from" => $from, "size" => $productPerPage,
'body' => [
"query" => [
"bool" => [
"must" => [
[
"multi_match" => [
"fields" => ["prod_name", "prod_seo_name"],
"type" => "phrase_prefix",
"query" => 'samsung'
]
],
//$conditionArr
[
"term"=> ["manuf_id"=>null]
]
]
]
]
],
];
Above query is not running. is there something I am missing? ANy help would be great.
You can pass this condition only in case when it necessary, like this:
$params = [
'index' => $this->client->getIndex(),
'type' => $this->client->getType(),
"from" => $from, "size" => $productPerPage,
'body' => [
"query" => [
"bool" => [
"must" => [
[
"multi_match" => [
"fields" => ["prod_name", "prod_seo_name"],
"type" => "phrase_prefix",
"query" => 'samsung'
]
],
]
]
]
],
];
if ($manufId > 0) {
$params['body']['query']['bool']['must'][] = [
'term' => ['manuf_id' => $manufId],
];
}

Aggregation by nested field after filter

I'm triying to get all the logs around a expecific geopoint, and group them by a subfield (context.id) but I'm having problems. I tried the nested aggregation, etc.. but I'm having no luck. I'm using the PHP library so I wrote the query as a php array. All is working until addign the aggregation query.
The exception throw is :
illegal_state_exception: Field data loading is forbidden on [context.id]
$params = [
'index' => 'logstash-*',
'type' => 'INFO',
'body' => [
'query' => [
'bool' => [
"must" => [
["term" => ["tags" => "producer"]],
["term" => ["tags" => "statistics"]],
["term" => ["message" => "view"]],
],
"filter" => [
"geo_distance" => [
"distance" => "10km",
"distance_type" => "plane",
"geoip.location" => [
"lat" => 40.4326058,
"lon" => -3.6996032
]
]
]
]
],
"aggs" => [
"context" => [
"nested" => [
"path" => "context"
],
"aggs" => [
"group_by_id" => [
"terms" => ["field" => "context.id"]
]
]
]
],
]
];
Can someone point me to the right query?
Finally, the problem here was the field. It was a indexed field I need to use the "context.id.raw" field instead.

ElasticSearch - Range query not working

I'm new to ElasticSearch so sorry if it's noob question. I'm trying to get users who has salary less than some value but I'm getting this error:
query_parsing_exception: No query registered for [salary]
My other queries works fine, only range query is failing, this is my code:
$items = $this->client->search([
'index' => 'offerprofiles',
'type' => 'profile',
'body' => [
'query' => [
'bool' => [
"must" => [
"match" => [
"jobcategories.name" => [
"query" => $query['category']
]
],
"range" => [
"salary" => [
"lt" => 20
]
]
],
"should" => [
"match" => [
"skills.name" => [
"query" => $query['skills']
]
]
],
"minimum_should_match" => 1
]
],
'size' => 50,
]
]);
If I remove range query then everything works fine, also I checked indexed values and salary is there (integer).
Thanks
The query is not a valid DSL. In the particular you are missing a bunch of brackets in the must clause. The must in the bool query should be an array of clauses instead in the above it is an object with key match and range.
Example :
$items = $this->client->search([
'index' => 'offerprofiles',
'type' => 'profile',
'body' => [
'query' => [
'bool' => [
"must" => [
[
"match" => [
"jobcategories.name" => [
"query" => $query['category']
]
]
],
[
"range" => [
"salary" => [
"lt" => 20
]
]
]
],
"should" => [
"match" => [
"skills.name" => [
"query" => $query['skills']
]
]
],
"minimum_should_match" => 1
]
],
'size' => 50,
]
]);

Categories