elasticsearch7.x Indexing a grandchild document - elasticsearch

Recently, I was studying the grandfather-grandchild documents in elasticsearch 7.x. I built an index myself and inserted data into it (see the code below), but I found that I can’t seem to find out the data.Did I do something wrong? thanks
mapping:
PUT /map
{
"mappings": {
"properties": {
"country": {
"properties": {
"id": {
"type": "integer"
},
"countryName": {
"type": "text"
}
}
},
"province": {
"properties": {
"id": {
"type": "integer"
},
"provinceName": {
"type": "text"
}
}
},
"city": {
"properties": {
"id": {
"type": "integer"
},
"cityName": {
"type": "text"
},
"attractions": {
"type": "text"
}
}
},
"my_join_field": {
"type": "join",
"relations": {
"country": "province",
"province": "city"
}
}
}
}
}
documents:
PUT map/_doc/1?refresh
{
"country.id": "1",
"country.countryName": "US",
"relationship": {
"name": "country"
}
}
PUT map/_doc/2?refresh
{
"country.id": "2",
"country.countryName": "CHINA",
"relationship": {
"name": "country"
}
}
PUT map/_doc/3?routing=1&refresh
{
"province.id": "3",
"province.provinceName": "losangeles",
"relationship": {
"name": "province",
"parent": "1"
}
}
PUT map/_doc/4?routing=1&refresh
{
"province.id": "4",
"province.provinceName": "chicago",
"relationship": {
"name": "province",
"parent": "1"
}
}
PUT map/_doc/5?routing=2&refresh
{
"province.id": "5",
"province.provinceName": "Anhui",
"relationship": {
"name": "province",
"parent": "2"
}
}
PUT map/_doc/6?routing=2&refresh
{
"province.id": "6",
"province.provinceName": "Shanghai",
"relationship": {
"name": "province",
"parent": "2"
}
}
PUT map/_doc/7?routing=2&refresh
{
"city.id": "7",
"city.cityName": "suzhou",
"city.attractions":"huangcangyu",
"relationship": {
"name": "city",
"parent": "5"
}
}
PUT map/_doc/8?routing=2&refresh
{
"city.id": "8",
"city.cityName": "maanshan",
"city.attractions":"caishiji",
"relationship": {
"name": "city",
"parent": "5"
}
}
query DSL:
GET /map/_search
{
"query": {
"has_child": {
"type": "province",
"query": {
"has_child": {
"type": "city",
"query": {
"match": {
"city.cityName": "maanshan"
}
}
}
}
}
}
}
There is no result from the query DSL above:
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 0,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
}
}

Related

How do I write correct query in nested document?

I have two indices: country and person
PUT person
{
"mappings": {
"properties": {
"info": {
"type": "nested",
"properties": {
"int_val": {"type": "integer"},
"str_val": {"type": "text"},
"field_id": {"type": "keyword"},
"country_id": {"type": "keyword"}
}
}
}
}
}
PUT country
{
"mappings": {
"properties": {
"country_ids": {"type": "keyword"}
}
}
}
PUT country/_doc/user1
{
"country_ids": ["111", "222", "333"]
}
PUT person/_doc/1
{
"info": [
{
"field_id": "1000",
"str_val": "Jack Kotlin",
"country_id": "444"
},
{
"field_id": "1000",
"str_val": "Jack Martin",
"country_id": "333"
},
{
"field_id": "1001",
"str_val": "Jack",
"country_id": "111"
},
{
"field_id": "2000",
"int_val": 30,
"country_id": "444"
},
{
"field_id": "2000",
"int_val": 30,
"country_id": "333"
},
{
"field_id": "2001",
"int_val": 30,
"country_id": "111"
}
]
}
If user1 queries '(field_id=1000 with str_val="Jack") & (field_id=2000 with int_val="Jack")' following result must be return:
{
"info": [
{
"field_id": "1000",
"str_val": "Jack Martin",
"country_id": "333"
},
{
"field_id": "2000",
"int_val": 30,
"country_id": "333"
}
]
}
Help me please!
I wrote a query for single part: (field_id=1000 with str_val="Jack")
GET person/_search
{
"query": {
"nested": {
"path": "info",
"query": {
"bool": {
"filter": [
{
"terms": {
"info.country_id": {
"index": "country",
"id": "user1",
"path": "country_ids"
}
}
}
],
"must": [
{"match": {"info.field_id": "1000"}},
{"match": {"info.str_val": "Jack"}}
]
}
},
"inner_hits": {}
}
},
"_source": false
}
and got a correct result:
{
"took" : 5,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 1.1530519,
"hits" : [
{
"_index" : "person",
"_id" : "1",
"_score" : 1.1530519,
"inner_hits" : {
"info" : {
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 1.1530519,
"hits" : [
{
"_index" : "person",
"_id" : "1",
"_nested" : {
"field" : "info",
"offset" : 1
},
"_score" : 1.1530519,
"_source" : {
"field_id" : "1000",
"str_val" : "Jack Martin",
"country_id" : "333"
}
}
]
}
}
}
}
]
}
}
but I don't know how to write a query for multi part!
The following query will show:
Documents with (id=1000 AND str_field=Jack) AND (id=2000 AND int_field=30)
GET person/_search
{
"query": {
"nested": {
"path": "info",
"query": {
"bool": {
"filter": [
{
"terms": {
"info.country_id": {
"index": "country",
"id": "user1",
"path": "country_ids"
}
}
},
{
"bool": {
"must": [
{
"bool": {
"must": [
{
"term": {
"info.field_id": "2000"
}
},
{
"match": {
"info.int_val": 30
}
}
]
}
},
{
"bool": {
"must": [
{
"term": {
"info.field_id": "1000"
}
},
{
"match": {
"info.str_val": "Jack"
}
}
]
}
}
]
}
}
]
}
},
"inner_hits": {}
}
},
"_source": false
}

Get data with different value but same field name in array of object with must?

I want to get data with different value but same field name in array of object
I have this data with stringFacets array of object contains criteria in elastict search 7.9
{
"took": 2238,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": [{
"stringFacets": [{
"name": "criterion",
"value": "Accès Wifi"
},
{
"name": "criterion",
"value": "Piscine"
}
]
}]
}
I want in my search get documents where stringFacets.name = "criterion" and stringFacets.value = "Piscine" and stringFacets.value = "Accès Wifi"
I tried this but no result
{
"query": {
"bool": {
"must": [
{
"nested": {
"path": "stringFacets",
"query": {
"bool": {
"must": [
{
"term": {
"stringFacets.name": "criterion"
}
},
{
"term": {
"stringFacets.value": "Piscine"
}
},
{
"term": {
"stringFacets.value": "Accès Wifi"
}
}
]
}
}
}
}
]
}
}
My mapping
{
"settings": {
"number_of_shards": "1"
},
"mappings": {
"dynamic": false,
"dynamic_templates": [{
"results": {
"mapping": {
"type": "text",
"index": false
},
"path_match": "results.*"
}
}
],
"properties": {
"#version" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"#timestamp" : {
"type" : "date"
},
"booleanFacets": {
"type": "nested",
"properties": {
"name": {
"type": "keyword"
},
"value": {
"type": "boolean"
}
}
},
"stringFacets": {
"type": "nested",
"properties": {
"name": {
"type": "keyword"
},
"value": {
"type": "keyword"
}
}
},
"locationFacets": {
"type": "geo_point"
},
"integerFacets": {
"type": "nested",
"properties": {
"name": {
"type": "keyword"
},
"value": {
"type": "long"
}
}
},
"decimalFacets": {
"type": "nested",
"properties": {
"name": {
"type": "keyword"
},
"value": {
"type": "double"
}
}
},
"datetimeFacets": {
"type": "nested",
"properties": {
"name": {
"type": "keyword"
},
"value": {
"type": "date"
}
}
},
"availabilities": {
"type": "nested",
"properties": {
"start": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss.SSSSSS"
},
"end": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss.SSSSSS"
},
"price": {
"type": "double"
},
"duration": {
"type": "long"
}
}
}
}
}
}
Thanks
The nested type is a specialized version of the object data type that
allows arrays of objects to be indexed in a way that they can be
queried independently of each other.
You are getting 0 results because there is no single object in your sample data that match all three conditions.
You can use inner_hits resulting in an inner nested query to automatically match the relevant nesting level, rather than the root
Modify your query as
{
"query": {
"nested": {
"path": "stringFacets",
"query": {
"bool": {
"should": [
{
"term": {
"stringFacets.name": "criterion"
}
},
{
"term": {
"stringFacets.value": "Piscine"
}
},
{
"term": {
"stringFacets.value": "Accès Wifi"
}
}
],
"minimum_should_match":2
}
},
"inner_hits": {}
}
}
}
Search Result will be
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 0.8754687,
"hits": [
{
"_index": "66170374",
"_type": "_doc",
"_id": "1",
"_score": 0.8754687,
"_source": {
"stringFacets": [
{
"name": "criterion",
"value": "Accès Wifi"
},
{
"name": "criterion",
"value": "Piscine"
}
]
},
"inner_hits": {
"stringFacets": {
"hits": {
"total": {
"value": 2,
"relation": "eq"
},
"max_score": 0.8754687,
"hits": [
{
"_index": "66170374",
"_type": "_doc",
"_id": "1",
"_nested": {
"field": "stringFacets",
"offset": 0
},
"_score": 0.8754687,
"_source": {
"name": "criterion", // note this
"value": "Accès Wifi"
}
},
{
"_index": "66170374",
"_type": "_doc",
"_id": "1",
"_nested": {
"field": "stringFacets",
"offset": 1
},
"_score": 0.8754687,
"_source": {
"name": "criterion", // note this
"value": "Piscine"
}
}
]
}
}
}
}
]
}

How to group distinct records in Elasticsearch

I have the following data in my Elasticsearch index:
{
"title": "Hello from elastic",
"name": "ABC",
"j_id": "1",
"date": '2021-03-02T12:29:31.356514'
},
{
"title": "Hello from elastic",
"name": "PQR",
"j_id": "1",
"date": '2021-03-02T12:29:31.356514'
},
{
"title": "Hello from elastic",
"name": "XYZ",
"j_id": "2",
"date": '2021-03-02T12:29:31.356514'
},
{
"title": "Hello from elastic",
"name": "MNO",
"j_id": "3",
"date": '2021-03-02T12:29:31.356514'
}
Now I want to get unique records on the basis of the id.
The expected output is:
{
"1": [{
"title": "Hello from elastic",
"name": "ABC",
"j_id": "1",
"date": '2021-03-02T12:29:31.356514'
},
{
"title": "Hello from elastic",
"name": "PQR",
"j_id": "1",
"date": '2021-03-02T12:29:31.356514'
}],
"2": [{
"title": "Hello from elastic",
"name": "XYZ",
"j_id": "2",
"date": '2021-03-02T12:29:31.356514'
}],
"3": [{
"title": "Hello from elastic",
"name": "MNO",
"j_id": "3",
"date": '2021-03-02T12:29:31.356514'
}]
}
I tried an aggregate query but it's giving me only the counts.
Also, I want to include latest record in my response.
How can I get sorted, unique records from Elasticsearch grouped by the id?
I want latest inserted data first
Assuming a minimal mapping covering the date and j_id fields:
PUT myindex
{
"mappings": {
"properties": {
"j_id": {
"type": "keyword"
},
"date": {
"type": "date"
}
}
}
}
you can leverage a terms aggregation whose sub-aggregation is an ordered top_hits aggregation:
POST myindex/_search?filter_path=aggregations.*.buckets.key,aggregations.*.buckets.sorted_hits.hits.hits._source
{
"size": 0,
"aggs": {
"by_j_id": {
"terms": {
"field": "j_id",
"size": 10,
"order": {
"max_date": "desc"
}
},
"aggs": {
"max_date": {
"max": {
"field": "date"
}
},
"sorted_hits": {
"top_hits": {
"size": 10,
"sort": [
{
"date": {
"order": "desc"
}
}
]
}
}
}
}
}
}
The URL parameter filter_path reduces the response body to closely mimic your required format:
{
"aggregations" : {
"by_j_id" : {
"buckets" : [
{
"key" : "1",
"sorted_hits" : {
"hits" : {
"hits" : [
{
"_source" : {
"title" : "Hello from elastic",
"name" : "ABC",
"j_id" : "1",
"date" : "2021-03-02T12:29:31.356514"
}
},
{
"_source" : {
"title" : "Hello from elastic",
"name" : "PQR",
"j_id" : "1",
"date" : "2021-03-02T12:29:31.356514"
}
}
]
}
}
},
{
"key" : "2",
"sorted_hits" : {
"hits" : {
"hits" : [
{
"_source" : {
"title" : "Hello from elastic",
"name" : "XYZ",
"j_id" : "2",
"date" : "2021-03-02T12:29:31.356514"
}
}
]
}
}
},
{
"key" : "3",
"sorted_hits" : {
"hits" : {
"hits" : [
{
"_source" : {
"title" : "Hello from elastic",
"name" : "MNO",
"j_id" : "3",
"date" : "2021-03-02T12:29:31.356514"
}
}
]
}
}
}
]
}
}
}

Elastic search query to retrieve specific object of array of objects from a document

I have below document in elastic and need to fetch only conversation where conversationId: 3dddf4ab from chat array, but I am getting the whole document
Document in Elastic:
{
"_index" : "myindex",
"_type" : "_doc",
"_id" : "1",
"_version" : 1,
"_seq_no" : 0,
"_primary_term" : 1,
"found" : true,
"_source" : {
"chatid" : "1",
"conversations" : [
{
"conversation" : {
"conversationId" : "3dddf4ab",
"startTime" : 1573555131306,
"question" : "abc",
"language" : "English",
"type" : "123",
"answer" : "weeqwew",
"feedback" : {
"rating" : 1,
"endTime" : 0,
"votes" : 1,
"likes" : 1
}
}
},
{
"conversation" : {
"conversationId" : "29363306",
"startTime" : 1567756384492,
"question" : "wer",
"language" : "English",
"type" : "456",
"answer" : "zxsz",
"feedback" : {
"rating" : 0,
"endTime" : 0,
"votes" : 0,
"likes" : 0
}
}
},
{
"conversation" : {
"conversationId" : "3dddf4ab",
"startTime" : 1573555131308,
"question" : "qwer",
"language" : "English",
"type" : "789",
"answer" : "hjhlh",
"feedback" : {
"rating" : 0,
"endTime" : 0,
"votes" : 0,
"likes" : 0
}
}
},
{
"conversation" : {
"conversationId" : "29363306",
"startTime" : 1567756384499,
"question" : "klklkl",
"language" : "English",
"type" : "674",
"answer" : "kjjj;",
"feedback" : {
"rating" : 2,
"endTime" : 0,
"votes" : 4,
"likes" : 4
}
}
}
]
}
}
Search query DSL in Kibana:
{
"query": {
"match": {
"chat.conversation.conversationId": {
"query": "3dddf4ab",
"type": "phrase"
}
}
}
}
Expected as below but getting the whole document:
This is the output which I am expecting instead I am getting the whole document including other conversationId's
{
"_index": "myindex",
"_type": "_doc",
"_id": "1",
"_version": 1,
"_seq_no": 0,
"_primary_term": 1,
"found": true,
"_source": {
"chatid": "1",
"conversations": [{
"conversation": {
"conversationId": "3dddf4ab",
"startTime": 1573555131306,
"question": "abc",
"language": "English",
"type": "123",
"answer": "weeqwew",
"feedback": {
"rating": 1,
"endTime": 0,
"votes": 1,
"likes": 1
}
}
},
{
"conversation": {
"conversationId": "3dddf4ab",
"startTime": 1573555131308,
"question": "qwer",
"language": "English",
"type": "789",
"answer": "hjhlh",
"feedback": {
"rating": 0,
"endTime": 0,
"votes": 0,
"likes": 0
}
}
}
]
}
}
Index Mapping
{
"mappings": {
"chatdb": {
"properties": {
"chatid": {
"type": "text"
},
"conversations": {
"type": "nested",
"properties": {
"conversation": {
"type": "object",
"properties": {
"conversationId": {
"type": "text"
},
"startTime": {
"type": "long"
},
"question": {
"type": "text"
},
"language": {
"type": "text"
},
"type": {
"type": "text"
},
"answer": {
"type": "text"
},
"feedback": {
"type": "object",
"properties": {
"rating": {
"type": "float"
},
"endTime": {
"type": "long"
},
"votes": {
"type": "integer"
},
"likes": {
"type": "integer"
}
}
}
}
}
}
}
}
}
}
}
Any help is much appreciated
Suven, you need to retrieve your inner hits from a nested query like below :
POST testindex/_search
{
"_source" : false,
"query": {
"nested": {
"path": "conversations",
"query": {
"term": {
"conversations.conversation.conversationId": {
"value": "3dddf4ab"
}
}
}
, "inner_hits": {
}
}
}
}
Response :
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 0.6931472,
"hits": [
{
"_index": "testindex",
"_type": "chatdb",
"_id": "L9qM_m4BavUEUOqEAqm-",
"_score": 0.6931472,
"inner_hits": {
"conversations": {
"hits": {
"total": 2,
"max_score": 0.6931472,
"hits": [
{
"_index": "testindex",
"_type": "chatdb",
"_id": "L9qM_m4BavUEUOqEAqm-",
"_nested": {
"field": "conversations",
"offset": 2
},
"_score": 0.6931472,
"_source": {
"conversation": {
"conversationId": "3dddf4ab",
"startTime": 1573555131308,
"question": "qwer",
"language": "English",
"type": "789",
"answer": "hjhlh",
"feedback": {
"rating": 0,
"endTime": 0,
"votes": 0,
"likes": 0
}
}
}
},
{
"_index": "testindex",
"_type": "chatdb",
"_id": "L9qM_m4BavUEUOqEAqm-",
"_nested": {
"field": "conversations",
"offset": 0
},
"_score": 0.6931472,
"_source": {
"conversation": {
"conversationId": "3dddf4ab",
"startTime": 1573555131306,
"question": "abc",
"language": "English",
"type": "123",
"answer": "weeqwew",
"feedback": {
"rating": 1,
"endTime": 0,
"votes": 1,
"likes": 1
}
}
}
}
]
}
}
}
}
]
}
}

Can't get join query in elastic

I got elasticsearch version 7.3 and two indexes, profiles and purchases,
here is their mappings:
\purchases
{
"purchases": {
"mappings": {
"properties": {
"product": {
"type": "keyword"
},
"profile": {
"type": "join",
"eager_global_ordinals": true,
"relations": {
"profiles": "purchases"
}
}
}
}
}
}
\profiles
{
"profiles": {
"mappings": {
"properties": {
"user": {
"type": "keyword"
}
}
}
}
}
I added one profile with user:abc, _id:1 and two purchases this way
{
"profile": {"name": "profiles", "parent": "1"},
"product" : "tomato",
}
{
"profile": {"name": "profiles", "parent": "1"},
"product" : "tomato 2",
}
Then I do search query for purchases
{
"query": {
"has_parent": {
"parent_type": "profiles",
"query": {
"query_string": {
"query": "user:abc"
}
}
}
}
}
And I get empty result, what is wrong?
As stated in the documentation of the Join datatype you can not create parent-child-relationships over multiple indices:
The join datatype is a special field that creates parent/child relation within documents of the same index.
If you would like to use the join datatype, you have to model it in one index.
UPDATE
This is how your mapping and the Indexing of the documents would look like:
PUT profiles-purchases-index
{
"mappings": {
"properties": {
"user":{
"type": "keyword"
},
"product":{
"type": "keyword"
},
"profile":{
"type": "join",
"relations":{
"profiles": "purchases"
}
}
}
}
}
Index parent document:
PUT profiles-purchases-index/_doc/1
{
"user": "abc",
"profile": "profiles"
}
Index child documents:
PUT profiles-purchases-index/_doc/2?routing=1
{
"product": "tomato",
"profile":{
"name": "purchases",
"parent": 1
}
}
PUT profiles-purchases-index/_doc/3?routing=1
{
"product": "tomato 2",
"profile":{
"name": "purchases",
"parent": 1
}
}
Run Query:
GET profiles-purchases-index/_search
{
"query": {
"has_parent": {
"parent_type": "profiles",
"query": {
"match": {
"user": "abc"
}
}
}
}
}
Response:
{
...
"hits" : [
{
"_index" : "profiles-purchases-index",
"_type" : "_doc",
"_id" : "2",
"_score" : 1.0,
"_routing" : "1",
"_source" : {
"product" : "tomato",
"profile" : {
"name" : "purchases",
"parent" : 1
}
}
},
{
"_index" : "profiles-purchases-index",
"_type" : "_doc",
"_id" : "3",
"_score" : 1.0,
"_routing" : "1",
"_source" : {
"product" : "tomato 2",
"profile" : {
"name" : "purchases",
"parent" : 1
}
}
}
]
}
}
Notice that you have to set the routing parameter to index the child documents. But please refer to the documentation for that.

Resources