I am attempting to make a Google like search using ElasticSearch and PHP. I have been reading a ElasticSearch book and I think I was to use simple_query_string query type that can take the keywords (or phrase) from a search box and try to find some of all of the terms entered.
I am using the PHP ElasticSearch library in my project and after connecting to my server I am trying to pass a $client->search($params) to my search to return a result.
I have this as my params array
$params =
[
'index' => 'letsmeetup',
'type' => 'person',
'body' =>
[
'query' =>
[
'simple_query_string' =>
[
'query' => $keywords,
'fields' => [
"first_name","last_name","bio","username","email_address","interests","skills"
]
]
]
]
];
I used a phrase like 'People who love php' and I get results. I tried 'real time web' (which is in my bio) as I get the correct result.
Problem is when I try 'Er', knowing there is a first_name of "Erin", or 'Neo', which I have "neo4j" in my bio, it's returning no results. Do I have the params array correct?
You need to use wildcards for these kind of queries
{
"query": {
"query_string": {
"fields": [ "first_name","last_name","bio","username","email_address","interests","skills"],
"query": "Er*"
}
}
}
This will match "Erin", "Eric", "Error" and so on.
You can find more information about Query String Syntax and wildcards here. https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html#query-string-syntax
I hope this helps!
Related
I am using REST API using PHP for fetching data from Elastic search with following code
$params = [
'index' => $search_index,
'type' => $search_type,
'from' => $_POST["from"],
'size' => $_POST["fetch"],
'body' => [
'query' => [
'bool' => [
'must' => [
[ 'match' => [ 'is_validated' => false ] ],
[ 'query_string' => [ 'query' => $search_str, 'default_operator' => 'OR' ] ]
]
]
]
]
];
Now, this is working perfectly and giving me my desired results.
The data that is returned from ES, has one column "result_source" and it has predefined values like CNN, BBC or YouTube etc.
What I need is, I want to filter results on "result_source" column in a way that, I can only fetch the results with the option I want. Like I want results that have "result_source" value only "YouTube" or only "BBC & CNN" or only "CNN or YouTube" etc.
I have already tried "Should" option, but it also returns the data with other values that I don't need. Not sure how to skip those values of "result_source" column in fetching results from ES.
Any help on this will be appreciated.
Thanks
Solved!!
I am replying to my own question, because I found a solution for it. May be it can help someone else in future.
If anyone is looking for a solution of searching within the field / column of Elastic search, here is what can be done.
[ 'query_string' => [ 'query' => $search_str.'(result_source:CNN OR result_source:BBC)', 'default_operator' => 'OR' ] ]
"result_source" is actually the field / column name of ES on which filter is applied to return results that have result_source=BBC or result_source=CNN.
This actually solved my issue.
I am new to ElasticSearch, and I am trying to solve a query the best way possible. I'm using PHP so it would be helpful to get to view it in that format, but I am ok to see it in any ElasticSearch DSL.
The query I need basically has to match Any or All words in multiple fields, say for example [title, description]
But I also want to only include any documents that can be filtered by any true case (example if the Document has "either" field1 = true OR field2 = true)
So example I search for "Nike boots that are green"
So for I would like to see results that would have Nike boots and Green
so I could just do
'query' => [
'query_string' => [
'fields' => [ 'title^6', 'description^3' ],
'query' => 'Nike boots that are green'
],
],
And I get all content that has the best score.
What I really want to add to my results are basically "filters" or "should " that if the Document either has field 'access' == 1 OR field 'permission' == 5, how will I do that. I know now that it needs to be a boolean.
Is it possible to have both query and boolean query in the same search?
the query_string query supports OR
'query' => [
'query_string' => [
'query' => 'access:1 OR permission:5'
],
],
We have created MongoDB query but it's not converted into PHP
MongoDB query
db.crawled_jobs.aggregate(
[
{
$geoNear: {
near: {
type: "Point",
coordinates: [-73.86, 41.07 ]
},
distanceField:"dist.calculated",
maxDistance: 100000,
includeLocs: "dist.location",
num: 1225,
spherical: true,
"query": { "title": /sales/ }
}
}
])
Mongodb query working fine and we get results
In php \MongoDB\Driver\Command
Create an array in PHP and use for MongoDB query
$queryString = [['$geoNear'=> ['near'=> [ 'type'=> "Point",'coordinates'=> [$lon,$lat] ], 'distanceField'=> "dist.calculated",'maxDistance'=> $maxDistance, 'includeLocs'=> "dist.location", 'num'=> 10000, 'spherical'=> true, 'query' => ['title' => '/sales/'] ] ] ];
after this query, MongoDB query look like this
db.crawled_jobs.aggregate([{"$geoNear":"near":"type":"Point","coordinates":[-73.86,41.07]},"distanceField":"dist.calculated","maxDistance":100000,"includeLocs":"dist.location","num":1225,"spherical":true,"query":{"title":"\/sales\/"}}}])
We didn't get result because it add backslash in query
"query":{"title":"\/sales\/"}
But we need like this "query": { "title": /sales/ }
Can anyone help us
\MongoDB\Driver\Command does not accept string :( it require the only array not string)
Fix it with this
'query' => ['title'=> array('$regex' => 'NYC')]
You need to use MongoDB\BSON\Regex class to generate regex as following:
'query' => ['title' => new MongoDB\BSON\Regex('sales')]
I want to use wildcard search using elastic search 2.3 using its official PHP client.
I am facing a issue which is like this:
Case 1. When i search for word wood, it returns the words which are having woodman, hollywood and hollywoodbolly.
Case 2. But when i search for hollywood, it does not return the words which are having hollywood in them.
However, everything is working fine when done in query string like this:
"query" => [
"query_string" => [
"query" => "*$keyword*",
"analyze_wildcard" => true,
"fields" => $fields
]
],
But when used like follwing, Case 2 is not working:
"query" => [
"bool" => [
"must" => [
[
"wildcard" => [
'name' => "*$keyword*",
]
],
[
"nested" => [
"path" => "address",
"score_mode" => "max",
"query" => [
"bool" => [
"must" => [..match[] parameters..]
]
]
]
]
]
]
I am not sure what I am doing wrong. Please help.
EDIT:
NOTE: I have made the field as not_analysed.
My query is returning cardboard when searching for card but not returning cardboard when searching for cardboard
Thanks.
Elasticsearch supports wildcard queries only on not_analyzed fields
So if you would like to use the wildcard capability you could either use it under the query_string object, or change the mapping for that field to index: not_analyzed and then you would be able to do a wildcard search.
I have a field called url that is set to not_analyzed when I index it:
'url' => [
'type' => 'string',
'index' => 'not_analyzed'
]
Here is my method to determine if a URL already exists in the index:
public function urlExists($index, $type, $url) {
$params = [
'index' => $index,
'type' => $type,
'body' => [
'query' => [
'match' => [
'url' => $url
]
]
]
];
$results = $this->client->count($params);
return ($results['count'] > 0);
}
This seems to work fine however I can't be 100% sure this is the correct way to find an exact match, as reading the docs another way to do the search is with the params like:
$params = [
'index' => $index,
'type' => $type,
'body' => [
'query' => [
'filtered' => [
'filter' => [
'term' => [
'url' => $url
]
]
]
]
]
];
My question is would either params work the same way for a not_analyzed field?
The second query is the right approach. term level queries/filters should be used for exact match. Biggest advantage is caching. Elasticsearch uses bitset for this and you will get quicker response time with subsequent calls.
From the Docs
Exclude as many document as you can with a filter, then query just the
documents that remain.
Also if you observe your output, you will find that _score of every document is 1 as scoring is not applied to filters, same goes for highlighting but with match query you will see different _score. Again From the Docs
Keep in mind that once you wrap a query as a filter, it loses query
features like highlighting and scoring because these are not features
supported by filters.
Your first query uses match which is basically used for analyzed fields e.g when you want both Google and google to match all your documents containing google(case insensitive) match queries are used.
Hope this helps!!