Avoiding cross-object searches with nested types in elastic search

I am trying to determine the best way to index a document in search of elasticity. I have a Doc document that has several fields:

Doc created_at updated_at field_a field_b 

But the Doc will also have some fields specific to individual users. For example, field_x will have a value of "A" for user 1, and field_x will have a value of "B" for user 2. For each document there will be a very limited number of users (usually 2, up to ~ 10). When the user searches in the field_x field, they should look for the value that belongs to them. I studied nested types in ES.

 Doc created_at updated_at field_x: [{ user: 1 field_x: A },{ user: 2 field_x: B }] 

When user 1 searches in the_and_field for the value “A”, this document should lead to a hit. However, this should not be when user 1 searches by the value of "B".

However, in accordance with the documents :

One of the problems when indexing internal objects that occur several times in a document is that there is a match for the search for a "cross-object"

Is there a way to avoid this behavior with nested types or should I learn another type?

Additional information on fulfilling such requests would be very valuable. Just by reading the docs, he stated that subqueries are not too different in terms of performance with respect to regular queries. If anyone has real experience, I would really like to hear it.

+7
elasticsearch
source share
1 answer

A nested type is what you are looking for, and don't worry about performance.

Before indexing documents, you need to establish a mapping for your documents:

 curl -XDELETE localhost:9200/index curl -XPUT localhost:9200/index curl -XPUT localhost:9200/index/type/_mapping -d '{ "type": { "properties": { "field_x": { "type": "nested", "include_in_parent": false, "include_in_root": false, "properties": { "user": { "type": "string" }, "field_x": { "type": "string", "index" : "not_analyzed" // NOTE* } } } } } }' 

* note: If your field really contains only special letters such as "A" and "B", you do not want to analyze the field, otherwise elasticsearch will delete these letters of the "word". If this was just your example and you are looking for the right words in your actual documents, delete this line and ask elasticsearch to parse the field.

Then index your docs:

 curl -XPUT http://localhost:9200/index/type/1 -d ' { "field_a": "foo", "field_b": "bar", "field_x" : [{ "user" : "1", "field_x" : "A" }, { "user" : "2", "field_x" : "B" }] }' 

And run your query:

 curl -XGET localhost:9200/index/type/_search -d '{ "query": { "nested" : { "path" : "field_x", "score_mode" : "avg", "query" : { "bool" : { "must" : [ { "term": { "field_x.user": "1" } }, { "term": { "field_x.field_x": "A" } } ] } } } } }'; 

This will lead to

 {"took":13,"timed_out":false,"_shards":{"total":5,"successful":5,"failed":0},"hits":{"total":1,"max_score":1.987628,"hits":[{"_index":"index","_type":"type","_id":"1","_score":1.987628, "_source" : { "field_a": "foo", "field_b": "bar", "field_x" : [{ "user" : "1", "field_x" : "A" }, { "user" : "2", "field_x" : "B" }] }}]}} 

However request

 curl -XGET localhost:9200/index/type/_search -d '{ "query": { "nested" : { "path" : "field_x", "score_mode" : "avg", "query" : { "bool" : { "must" : [ { "term": { "field_x.user": "1" } }, { "term": { "field_x.field_x": "B" } } ] } } } } }'; 

will not return any results

 {"took":6,"timed_out":false,"_shards":{"total":5,"successful":5,"failed":0},"hits":{"total":0,"max_score":null,"hits":[]}} 
+5
source share

All Articles