Elasticsearch: Query nested array - elasticsearch

I'm trying to write multi-fields queries for searching function, but there are some problems with full-text search in nested array
My data has format like this:
{
"name": "[Sample] AAA",
"variant": [
["s", "black"],
["l", "white"],
],
},
{
"name": "[Sample] BBB",
"variant": [
["s", "white"],
["l", "black"],
],
},
With input sample s black or sample black s, I'd like to find all documents having exact s and black options like [Sample] AAA but not [Sample] BBB. I've tried nested query but didn't get the desired result. Is there any way to refactor the data format and write the optimal mapping?

Create the Index with the following mappings
PUT my_index
{
"mappings": {
"properties": {
"name": {
"type": "text"
},
"variant": {
"type": "nested",
"properties": {
"0": {
"type": "keyword"
},
"1": {
"type": "text"
}
}
}
}
}
}
Put the sample documents
PUT my_index/_doc/1
{
"name": "[Sample] AAA",
"variant": [
["s", "black"],
["l", "white"],
]
}
PUT my_index/_doc/2
{
"name": "[Sample] BBB",
"variant": [
["s", "white"],
["l", "black"],
]
}
GET the docs
GET my_index/_search
{
"query": {
"bool": {
"must": [
{
"nested": {
"path": "variant",
"query": {
"bool": {
"must": [
{
"match": {
"variant.key": "s"
}
},
{
"match": {
"variant.value": "black"
}
}
]
}
}
}
}
]
}
}
}

Related

Elastic Search must and Should Combination

I'm new to elastic search and I've the below data in ElasticSearch.
{
"User": "A",
"Event": "E1"
},
{
"User": "A",
"Event": "E2"
}
{
"User": "A",
"Event": "E3"
},
{
"User": "A",
"Event": "E4"
}
Now I want to fetch data like below i.e
(Event='E1') AND (Event='E2'OR Event='E3' OR Event='E4')
I went through elastic search doc and found that should is used as OR and must is used as AND but I'm a bit confused about how can I form the query.
I used the below query:-
{
"from": 0,
"size": 10,
"query": {
"bool": {
"must": [
{
"match": {
"Event": "E1"
}
},
{
"bool": {
"should": [
{
"match": {
"Event": "E2"
}
},
{
"match": {
"Event": "E3"
}
},
{
"match": {
"Event": "E4"
}
}
]
}
}
]
}
}
}
But the output is not as expected.
The help is appreciated thanks in advance!!!

ElasticSearch query nested path filter OR

I have following index:
PUT /ab11
{
"mappings": {
"properties": {
"product_id": {
"type": "keyword"
},
"data": {
"type": "nested",
"properties": {
"p_id": {
"type": "keyword"
}
}
}
}
}
}
PUT /ab11/_doc/1
{
"product_id": "123",
"data": [
{
"p_id": "a"
},
{
"p_id": "b"
},
{
"p_id": "c"
}
]
}
I want to do query like following sql does(NOTE: I want to do filter not query, because I don't care about score) :
select * from abc11 where data.pid = "a" or data.pid = "b"
You can do it like this because the terms query has OR semantics by default:
{
"query": {
"nested": {
"path": "data",
"query": {
"terms": {
"data.p_id": [
"a",
"b"
]
}
}
}
}
}
Basically, select all documents which have either "a" or "b" in their data.p_id nested docs.

search in array of objects in elasticsearch

I am using elasticsearch-6.4.3
I have created an index test_index with the following mapping:
PUT test_index
{
"mappings": {
"_doc": {
"properties": {
"name": {
"type": "keyword"
},
"segments": {
"type": "nested",
"properties": {
"f1": {
"type": "keyword"
},
"f2": {
"type": "integer"
}
}
}
}
}
}
}
I inserted a document in the index with the following command:
POST /test_index/_doc
{
"name": "ABC",
"segments": [{
"f1": "abc",
"f2": 123
},
{
"f1": "def",
"f2": 124
}]
}
I have an array of values say arr = ["def", "xyz"]. I want to match all the documents whose atleast one of the f1 field in segments field match with any of the values in the given array arr.
You can call it something like array_intersect to easier to understand.
I am trying something like this:
GET /test_index/_search
{
"query": {
"nested": {
"path": "segments",
"query": {
"bool": {
"must": [
{
"terms": {
"f1": [
"def",
"xyz"
]
}
}
]
}
}
}
}
}
I am getting no results as the output.
Expected output: The document should match as "def" is present as value of f1 in the document.
You would need to specify the full path in your terms query as segments.f1 instead of f1 for nested query.
Modify the query as below:
POST test_index/_search
{
"query":{
"nested":{
"path":"segments",
"query":{
"bool":{
"must":[
{
"terms": {
"segments.f1": ["def","xyz"] <---- Mention full path here
}
}
]
}
}
}
}
}
Hope this helps!

ElasticSearch Nested Query Does not work as expected

I need a quick help, i need to fetch the entire document only when my certain conditions are fulfilled in that same array.
Example
Conditions when in one array block all these three conditions fulfill. i.e.
"profile.bud.buddies.code": "1"
"profile.bud.buddies.moredata.key":"one"
"profile.bud.buddies.moredata.val": "0"
Unfortunately right now it is going through the entire document and trying to match the values in each of those arrays so it could be so that code=1 gets matched in one array, key=one in some other array and val=0 in the third array. What happens it in this case it returns me the entire document, whereas actually this was not fulfilled in one array alone so shouldn't have returned me the document.
I made the moredata as nested type but still cannot get through. Please help.
Query I am using
"query": {
"bool": {
"should": [
{
"match": {
"profile.bud.buddies.code": "1"
}
}
]
},
"nested": {
"path": "profile.bud.buddies.moredata",
"query": {
"bool": {
"must": [
{
"match": {
"profile.bud.buddies.moredata.key": "one"
}
},
{
"match": {
"profile.bud.buddies.moredata.val": "0"
}
}
]
}
}
}
}
Document Structure
"profile": {
"x":{},
"y":{},
"a":{},
"b":{},
"bud":{
"buddies": [
{
"code":"1",
"moredata": [
{
"key": "one",
"val": 0,
"setup": "2323",
"data": "myid"
},
{
"key": "two",
"val": 1,
"setup": "23",
"data": "id"
}]
},
{
"code":"2",
"moredata": [
{
"key": "two",
"val": 0,
"setup": "2323",
"data": "myid"
},
{
"key": "three",
"val": 1,
"setup": "23",
"data": "id"
}]
}]
}
This is how i have marked the mappings;
"profile": {
"bug": {
"properties": {
"buddies": {
"properties": {
"moredata": {
"type": "nested",
"properties": {
"key": {"type": "string"},
"val": {"type": "string"}
Your query structure is incorrect, it should be something like
"query": {
"bool": {
"must": [{
"match": {
"profile.bud.buddies.code": "1"
}
},
{
"nested": {
"path": "profile.bud.buddies.moredata",
"query": {
"bool": {
"must": [{
"match": {
"profile.bud.buddies.moredata.key": "one"
}
},
{
"match": {
"profile.bud.buddies.moredata.val": "0"
}
}
]
}
}
}
]
}
}
}
where the nested query is inside of the array of must clauses of the outer bool query. Note that profile.bud.buddies.moredata must be mapped as a nested data type.

Bool AND search in properties in ElasticSearch

I've got a very small dataset of documents put in ES :
{"id":1, "name": "John", "team":{"code":"red", "position":"P"}}
{"id":2, "name": "Jack", "team":{"code":"red", "position":"S"}}
{"id":3, "name": "Emily", "team":{"code":"green", "position":"P"}}
{"id":4, "name": "Grace", "team":{"code":"green", "position":"P"}}
{"id":5, "name": "Steven", "team":[
{"code":"green", "position":"S"},
{"code":"red", "position":"S"}]}
{"id":6, "name": "Josephine", "team":{"code":"red", "position":"S"}}
{"id":7, "name": "Sydney", "team":[
{"code":"red", "position":"S"},
{"code":"green", "position":"P"}]}
I want to query ES for people who are in the red team, with position P.
With the request
curl -XPOST 'http://localhost:9200/teams/aff/_search' -d '{
"query": {
"bool": {
"must": [
{
"match": {
"team.code": "red"
}
},
{
"match": {
"team.position": "P"
}
}
]
}
}
}'
I've got a wrong result.
ES gives
"name": "John",
"team":
{ "code": "red", "position": "P" }
and
"name": "Sydney",
"team":
[
{ "code": "red", "position": "S"},
{ "code": "green", "position": "P"}
]
For the last entry, ES took the property code=red in the first record and took the property position=P in the second record.
How can I specify that the search must match the 2 two terms in the same record (within or not a list of nested records) ?
In fact, the good answer is only the document 1, with John.
Here is the gist that creates the dataset :
https://gist.github.com/flrt/4633ef59b9b9ec43d68f
Thanks in advance
When you index document like
{
"name": "Sydney",
"team": [
{"code": "red", "position": "S"},
{"code": "green","position": "P"}
]
}
ES implicitly create inner object for your field (team in particular example) and flattens it to structure like
{
'team.code': ['red', 'green'],
'team.position: ['S', 'P']
}
So you lose your order. To avoid this you need explicitly put nested mapping, index your document as always and query them with nested query
So, this
PUT so/nest/_mapping
{
"nest": {
"properties": {
"team": {
"type": "nested"
}
}
}
}
PUT so/nest/
{
"name": "Sydney",
"team": [
{
"code": "red",
"position": "S"
},
{
"code": "green",
"position": "P"
}
]
}
GET so/nest/_search
{
"query": {
"nested": {
"path": "team",
"query": {
"bool": {
"must": [
{
"match": {
"team.code": "red"
}
},
{
"match": {
"team.position": "P"
}
}
]
}
}
}
}
}
will result with empty hits.
Further reading on relation management: https://www.elastic.co/blog/managing-relations-inside-elasticsearch
You can use a Nested Query so that your searches happen individually on the subdocuments in the team array, rather than across the entire document.
{
"query": {
"bool": {
"must": [
{
"nested": {
"path": "team",
"query": {
"bool": {
"must": [
{ "match": { "team.code": "red" } },
{ "match": { "team.position": "P" } }
]
}
}
}
}
]
}
}
}

Resources