I've just downloaded and installed the last version of Elasticsearch on my Windows machine. I did my first search queries and everything seemed to work ok. However. when I try to highlight the search results, I fail. So, this is how my query looks like:
$params = [
'index' => 'test_index',
'type' => 'test_index_type',
'body' => [
'query' => [
'bool' => [
'should' => [ 'match' => [ 'field1' => '23' ] ]
]
],
'highlight' => [
'pre_tags' => "<em>",
'post_tags' => "</em>",
'fields' => (object)Array('field1' => new stdClass),
'require_field_match' => false
]
]
]
$res = $client->search($params);
On the whole the query itself works nice - the results are filtered. In the console I see, that all documents indeed contain "23" value in their field1 field. However, these tags - <em></em> are simply not added to the result. What I see is just the raw value in field1 like "some text 23", "23 another text". It is not what I expect to see - "some text <em>23</em>", "<em>23</em> another text". So, what is wrong with that and how can I fix it?
From the manual:
The value of pre_tags and post_tags should be an array (however if you don't want to change the em tags you can ignore them, they already set as default).
The fields value should be an array, key is the field name and the value is an array with the field options.
Try this fix:
$params = [
'index' => 'test_index',
'type' => 'test_index_type',
'body' => [
'query' => [
'bool' => [
'should' => [ 'match' => [ 'field1' => '23' ] ]
]
],
'highlight' => [
// 'pre_tags' => ["<em>"], // not required
// 'post_tags' => ["</em>"], // not required
'fields' => [
'field1' => new \stdClass()
],
'require_field_match' => false
]
]
];
$res = $client->search($params);
var_dump($res['hits']['hits'][0]['highlight']);
update
Did a double check, the value of the field in the fields array should be an object (which is a requirement, not exactly the same as other options).
The pre/post_tags can also be strings (and not array).
Did you check the correct response? $res['hits']['hits'][0]['highlight']
The important thing to notice is that the highligted results goes into the highlight array - $res['hits']['hits'][0]['highlight'].
Related
$params = [
'from' => $from,
'size' => config('app.pagination'),
'index' => $index,
//'type' => $this->type,
'body' => [
'query' => [
'bool' => [
'filter' => [
'term' => $where
],
'must' => [
'multi_match' => [
'query' => $match,
'fields'=>$fields,
'fuzziness' => "AUTO:1,5",
]
]
],
]
]
];
Hello, I don't have a problem with my query above.
For example, I am looking for a pizza. I am writing pizaz again.
These queries return the correct records to me.
But I have a problem.
It doesn't return anything when you type piz.
How can I solve this problem? I want it to work when I write it missing.
Add minimum_should_match parameter to your query.
Using minimum_should_match sets a threshold (absolute number, percentage, or combination of these) for matching clauses in boolean queries.
As you know from docs
If the bool query includes at least one should clause and no must or
filter clauses, the default value is 1. Otherwise, the default value
is 0.
I'm trying to perform a basic login operation where my view (front end part) accepts a username and password through a form
So in SQL, I must have an example query:
SELECT * FROM users WHERE username = $_POST['username'] AND password = $_POST['password'];
According to the official documentation of Elasticsearch PHP API, it must go like this:
$params = [
'index' => 'myIndex',
'type' => 'myType',
'body' => [
'query' => [
"bool" => [
"must" => [
"match" => [
"username" => 'email#email.com',
],
"match" => [
"password" => 'mypassword',
],
]
]
]
]
];
Unfortunately, it is displaying A LOT of documents so I presumed it's performing the OR operator instead of matching them together
FYI, if you would ever wonder why would there be so many documents displayed according to the "hits" property above, there are literally many user documents with the same password
Main Question
Is there any proper ES query to properly match my username AND password so I could only retrieve one document? I've been searching through with the official documentation, but nothing succeeds the desired output
Thank you very much!
You're almost there. You need to enclose your match queries in one more array, otherwise your bool/must becomes an associative array and that's not what you want (i.e. the second match filter gets discarded).
$params = [
'index' => 'myIndex',
'type' => 'myType',
'body' => [
'query' => [
"bool" => [
"must" => [
--> [
"match" => [
"username" => 'email#email.com',
]
--> ],
--> [
"match" => [
"password" => 'mypassword',
]
]
--> ]
]
]
]
];
With the help of sir Val, I was able to formulate a technique to try work-arounds for my query, and was able to display the result with the following:
$params = [
'index' => $index,
'type' => 'index',
'size' => 250,
'body' => [
'query' => [
'bool' => [
'must' => [
[
"match" => [
"usr_username" =>
[
"query" => $username,
"operator" => "and"
]
]
],
[
"match" => [
"usr_password" => [
"query" => $password,
"operator" => "and"
]
]
]
]
]
]
]
];
I have the structure below which I need to turn into json_encoded. To finally get it decoded and get an object.
This will allow me to have multiple objects with the name message and loop through them and process each message individually.
However when encoded, php will only encode the key and one of the message arrays—the last one.
$setup = [
'key' => 'demo-7hn3fh83un3yhvfjvnjgknfhjnvf',
'message' => [
'number' => [
'+39XXXXXXXX',
'+34XXXXXXXX',
'+49XXXXXXXX'
],
'text' => 'Sample msg 123...',
],
'message' => [
'number' => [
'+50XXXXXXXX',
'+50XXXXXXXX'
],
'text' => 'Something...',
]
];
Is there a way to encode multiple arrays with the same name?
You've overlooked the root issue:
$foo = [
'bar' => 1,
'bar' => 2,
'bar' => 3,
];
var_export($foo);
array (
'bar' => 3,
)
Thanks for the tips everyone. I ended up modifying the structure like below...
The reason why I am going with a structure like this is cause it allows me to submit multiple messages to multiple users with a single request.
$setup = [
'key' => 'demo-7hn3fh83un3yhvfjvnjgknfhjnvf',
'message' => [
[
'number' => [
'+39XXXXXXXX',
'+34XXXXXXXX',
'+49XXXXXXXX'
],
'text' => 'Sample msg 123...'
],
[
'number' => [
'+50XXXXXXXX',
'+50XXXXXXXX'
],
'text' => 'Something...'
]
]
];
Consider this PHP array for defining a search query on elasticsearch
$searchParams = [
'index' => $index_name,
'type' => 'nginx-access',
'size' => 1000,
'sort' => ['_score'],
'fields' => ["remote_addr", "#timestamp", "request", "method", "status"],
'body' => [
// 'min_score' => 4,
'query' => [
'bool' => [
'must' => [
['match' => ['status' => '200']],
['match' => ['method' => 'POST']],
['match' => ['request' => '/wp-login.php']],
],
]
]
]
];
$results = $this->client->search($searchParams);
var_dump($results);
Notice that 'min_score' is commented out. The array of results returns everything as expected, however I only want results that match all of the criteria. I thought this is what query->bool->must is supposed to do, however near the end of the dataset I am getting matches for other seemingly random things as well.
If I run it with min_score then I'm always going to get the results I want, but this does not seem the right way to do it.
Am I missing something obvious here?
I'm having trouble duplicating my MySQL delete query in elastic search, I am using this documentation: http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/docs-delete-by-query.html using the PHP wrapper for Laravel.
I'm trying this:
$this->es->deleteByQuery([
'index' => 'users',
'type' => 'user',
'body' => [
'query' => [
'term' => ['field1' => $this->field1],
'term' => ['field2' => $this->field2],
'term' => ['temp' => 0]
]
]
]);
Its suppose to be a DELETE FROM users WHERE field1 = $this->field1 AND field2 = $this->field2...
I'm having trouble translating the WHERE AND syntax to Elastic Search.
Any help?
Your second comment was mostly correct:
I think I have have gone overboard right now. I have body => query =>
filter => filtered => bool => must => term, term, term. Do I need the
filter => filtered arrays?
The bool filter is preferable over the bool query, since filtering is often much faster than querying. In your case, you are simply filtering documents that have the various terms, and don't want them contributing to the score, so filtering is the correct approach.
This should be done though the query clause, however, since the top-level filter clause is used for a different purpose (filtering facets/aggregations...it was in-fact renamed to post_filter in 1.0 to signify that it is a "post filtering" operation).
Your query should look something like this:
$this->es->deleteByQuery([
'index' => 'users',
'type' => 'user',
'body' => [
'query' => [
'filtered' => [
'filter' => [
'must' => [
['term' => ['field1' => $this->field1]],
['term' => ['field2' => $this->field2]],
['term' => ['temp' => 0]]
]
]
]
]
]
]);