Match documents in elasticsearch with AND and OR on different fields - elasticsearch

I am new to elastic search and I am working with MySQL and MongoDB. I want to write the query which gives products which are active and it's name or brand_name or model_number or category contains a specific word.
Here is MySQL query.
SELECT * FROM products WHERE active=0 AND (name LIKE '%car%' OR brand_name LIKE '%car%' OR model_number LIKE '%car%' OR category LIKE '%car%');
I already tried with the below query in elastic search, but it's just AND operator.
"query": {
"bool": {
"must": [
{"match": {"active": "1"}},
{"regexp": {"name": "cars.*"}},
{"regexp": {"brand_data.brand_name": "cars.*"}},
{"regexp": {"model_number": "cars.*"}},
]
}
}
Can anyone help me to write this query in elasticsearch.

Short answer - for OR you can use should occurrence of boolean query.
Long answer with example:
It can be done in several ways, but I want point you to one detail. If you need to search only active=1 or active=0 results, it will be better to use filter occurrence in your query. It will give you better performance and caching.
The clause (query) must appear in matching documents. However unlike must the score of the query will be ignored. Filter clauses are executed in filter context, meaning that scoring is ignored and clauses are considered for caching.
So I can propose you this query:
{
"query": {
"bool": {
"filter": {
"term": {
"active": "1"
}
},
"should": [
{
"regexp": {
"name": "cars.*"
}
},
{
"regexp": {
"brand_data.brand_name": "cars.*"
}
},
{
"regexp": {
"model_number": "cars.*"
}
}
]
}
}
}

You are looking for a 'or' nested inside an 'and' clause. this is the correct format:
"query": {
"bool": {
"must": [
{"match": {"active": "1"}},
{"bool":{"should":[
{"regexp": {"name": "cars.*"}},
{"regexp": {"brand_data.brand_name": "cars.*"}},
{"regexp": {"model_number": "cars.*"}}]}}
]
}
}

Related

Elasticsearch Multi match and exact matches

My knowledge of Elasticsearch is a bit limited, so what I want to do might not even be possible.
Say I have an ecommerce where I want to be able to freely search on the article names and other fields, but I also want to search on exact article codes aswell. Is this possible in the same query?
Example:
"articlecode": "v400",
"name": "Earplugs for humans"
}
{
"articlecode": "b6655",
"name": "Hammer 400"
}
So can a query be written that combines both multimatch and terms? So that If I search for '400' I get 2 results, but if I search for v400 I just get one result as it is an exact match on the "articlecode"-field.
Below is our current query, where i have an ngram on the "name" field and where I use the term-keyword on the language-field.
{
"size": 10,
"query": {
"bool": {
"must": {
"multi_match": {
"query": "v400",
"fields": [
"articlecode^10",
"name^7"
]
}
},
"filter": {
"term": {
"IdLang.keyword": "sv"
}
}
}
}
}
Have you ever thought of using query_string instead of multi_match? Then you can use wildcard in your search:
{
"size": 10,
"query": {
"bool": {
"must": {
"query_string": {
"query": "*v400",
"fields": [
"articlecode^10",
"name^7"
]
}
}
}
}
}
If you want to search with 400 anywhere in the 2 fields, you can do *400*, or only leading or trailing, depending on what you want.

Elastic search query using python list

How do I pass a list as query string to match_phrase query?
This works:
{"match_phrase": {"requestParameters.bucketName": {"query": "xxx"}}},
This does not:
{
"match_phrase": {
"requestParameters.bucketName": {
"query": [
"auditloggingnew2232",
"config-bucket-123",
"web-servers",
"esbck-essnap-1djjegwy9fvyl",
"tempexpo",
]
}
}
}
match_phrase simply does not support multiple values.
You can either use a should query:
GET _search
{
"query": {
"bool": {
"should": [
{
"match_phrase": {
"requestParameters.bucketName": {
"value": "auditloggingnew2232"
}
}
},
{
"match_phrase": {
"requestParameters.bucketName": {
"value": "config-bucket-123"
}
}
}
]
},
...
}
}
or, as #Val pointed out, a terms query:
{
"query": {
"terms": {
"requestParameters.bucketName": [
"auditloggingnew2232",
"config-bucket-123",
"web-servers",
"esbck-essnap-1djjegwy9fvyl",
"tempexpo"
]
}
}
}
that functions like an OR on exact terms.
I'm assuming that 1) the bucket names in question are unique and 2) that you're not looking for partial matches. If that's the case, plus if there are barely any analyzers set on the field bucketName, match_phrase may not even be needed! terms will do just fine. The difference between term and match_phrase queries is nicely explained here.

Elastic Search 1.7 - Full Like search like SQL

Im using old version of elastic search and I can't find a way to allow full like search like sql: '%%'
I have to search a non pre-known data so the "columns" are not known.
Ex.
I have this columns ad an example of row:
source,dest,message
eth0, eth1, DELIVERY 3015801: SUCCESS: DID
In the search form, a user write something like this:
+message:"delivery"
or
+message:"delivery" and +source:"eht0"
The row is returned succesfully.
Unfortunally if they write:
+message:"success"
it return no row because of ":"
I need to allow user to write somethig like:
+message:"success*"
This is the query submitted. I have timerange filter and then the query :
{
"query": {
"filtered": {
"filter": {
"bool": {
"must": [
{
"range": {
"#timestamp": {
"from": 1561615860000,
"to": 1561619519000
}
}
}
]
}
},
"query": {
"bool": {
"should": [
{
"query_string": {
"query": "+message:\"success\""
}
}
]
}
}
}
},
"sort": [
{
"#timestamp": {
"order": "desc"
}
}
]
}
Is there a way to translate my text search in something like sql
message like 'success%'
Thanks.
Is that an analyzed or a not-analyzed field? Maybe a prefix query is what you want for that.
But generally:
This version is more than dead. Please upgrade.
This is not a relational database. If you try to translate the concepts 1:1 you will not get the most out of it. Documentation or courses will help you to move into proper search and away from LIKE searches.

Elasticsearch wildcard VS querystring

I've found 2 approaches for Like-Search in Elasticsearch. Which one of those whould I choose? They seem to have the same behaviour. Or is there even a better one?
query_string:
"query": {
"bool": {
"filter": [
{
"query_string": {
"query": "*quick*",
"fields": [
"text"
]
}
}
]
}
}
wildcard:
"query": {
"bool": {
"must": [
{
"wildcard": {
"text": "*quick*"
}
}
]
}
}
SQL would be WHERE text like '%quick%'
I think, the difference is, that in the filter query no scores are calculated. In the documentation:
In filter context, a query clause answers the question “Does this document match this query clause?” The answer is a simple Yes or No — no scores are calculated.
So i would use wildcard query. There you can use * for more characters and ? for only one character - depending on your needs. And here, the scores are calculated.

Elastic Search Query (a like x and y) or (b like x and y)

Some background info: In the bellow example user searched for "HTML CSS". I split each word from the search string and created the SQL query seen bellow.
Now I am trying to make an elastic search query that has the same logic as the following SQL query:
SELECT
title, description
FROM `classes`
WHERE
(`title` LIKE '%html%' AND `title` LIKE '%css%') OR
(description LIKE '%html%' AND description LIKE '%css%')
Currently, half way there but can't seem to get it right yet.
{
"query": {
"bool": {
"must": [
{
"term": {
"title": "html"
}
},
{
"term": {
"title": "css"
}
}
]
}
},
"_source": [
"title"
],
"size": 30
}
Now I need to find how to add follow logic
OR (description LIKE '%html%' AND description LIKE '%css%')
One important point is that I need to only fetch documents that have both words in either title or disruption. I don't want to fetch documents that have only 1 word.
I will update questions as I find more info.
Update: The chosen answer also provides a way to boost scoring based on the field.
Can you try following query. You can use should for making or operation
{
"query": {
"bool": {
"should": [
{
"bool": {
"must": [
{
"match": { // Go for term if your field is analyzed
"title": {
"query": "html css",
"operator": "and",
"boost" : 2
}
}
}
]
}
},
{
"bool": {
"must": [
{
"match": {
"description": {
"query": "html css",
"operator": "and"
}
}
}
]
}
}
],
"minimum_number_should_match": 1
}
},
"_source": [
"title",
"description"
]
}
Hope this helps!!
I feel most appropriate query to be used in this case is multi_match.
multi_match query is convenient way of running the same query on
multiple fields.
So your query can be written as:
GET /_search
{
"_source": ["title", "description"],
"query": {
"multi_match": {
"query": "html css",
"fields": ["title^2", "description"],
"operator":"and"
}
}
}
_source filters the dataset so that only fields mentioned in array
will be displayed in results.
^2 denotes boosting title field with the number 2
operator:and makes sure that all terms in query must be matched
in either fields
From the elasticsearch 5.2 doc:
One option is to use the nested datatype instead of the object datatype.
More details here: https://www.elastic.co/guide/en/elasticsearch/reference/5.2/nested.html
Hope this helps

Resources