-
Notifications
You must be signed in to change notification settings - Fork 25.6k
QL: complex nested field types mappings fix #69368
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
ca9fff4
803d382
51947e0
2169a10
39e6fc6
1479727
6e7222d
694a8de
b740d00
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,6 +16,8 @@ | |
|
|
||
| import java.io.IOException; | ||
| import java.time.ZoneId; | ||
| import java.util.ArrayList; | ||
| import java.util.Iterator; | ||
| import java.util.List; | ||
| import java.util.Map; | ||
| import java.util.Objects; | ||
|
|
@@ -81,13 +83,66 @@ public Object extract(SearchHit hit) { | |
| Object value = null; | ||
| DocumentField field = null; | ||
| if (hitName != null) { | ||
| // a nested field value is grouped under the nested parent name (ie dep.dep_name lives under "dep":[{dep_name:value}]) | ||
| field = hit.field(hitName); | ||
| value = unwrapFieldsMultiValue(extractNestedField(hit)); | ||
| } else { | ||
| field = hit.field(fieldName); | ||
| if (field != null) { | ||
| value = unwrapFieldsMultiValue(field.getValues()); | ||
| } | ||
| } | ||
| return value; | ||
| } | ||
|
|
||
| /* | ||
| * For a path of fields like root.nested1.nested2.leaf where nested1 and nested2 are nested field types, | ||
| * fieldName is root.nested1.nested2.leaf, while hitName is root.nested1.nested2 | ||
| * We first look for root.nested1.nested2 or root.nested1 or root in the SearchHit until we find something. | ||
| * If the DocumentField lives under "root.nested1" the remaining path to search for (in the DocumentField itself) is nested2. | ||
| * After this step is done, what remains to be done is just getting the leaf values. | ||
| */ | ||
| @SuppressWarnings("unchecked") | ||
| private Object extractNestedField(SearchHit hit) { | ||
| Object value; | ||
| DocumentField field; | ||
| String tempHitname = hitName; | ||
| List<String> remainingPath = new ArrayList<>(); | ||
| // first, search for the "root" DocumentField under which the remaining path of nested document values is | ||
| while ((field = hit.field(tempHitname)) == null) { | ||
| int indexOfDot = tempHitname.lastIndexOf("."); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this guaranteed to return a non-negative?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Mentioning it here, but happy to open an issue if better (or just drop it, if wrong): selecting
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice catch! That's an older problem -
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
We should prevent the error from occurring - looking at the stacktrace this seems to have been addressed yet I'm mentioning to double check this is indeed the case.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @bpintea this change should fix the |
||
| if (indexOfDot < 0) {// there is no such field in the hit | ||
| return null; | ||
| } | ||
| remainingPath.add(0, tempHitname.substring(indexOfDot + 1)); | ||
| tempHitname = tempHitname.substring(0, indexOfDot); | ||
| } | ||
| if (field != null) { | ||
| value = unwrapFieldsMultiValue(field.getValues()); | ||
| // then dig into DocumentField's structure until we reach the field we are interested into | ||
| if (remainingPath.size() > 0) { | ||
| List<Object> values = field.getValues(); | ||
| Iterator<String> pathIterator = remainingPath.iterator(); | ||
| while (pathIterator.hasNext()) { | ||
| String pathElement = pathIterator.next(); | ||
| Map<String, List<Object>> elements = (Map<String, List<Object>>) values.get(0); | ||
| values = elements.get(pathElement); | ||
| /* | ||
| * if this path is not found it means we hit another nested document (inner_root_1.inner_root_2.nested_field_2) | ||
| * something like this | ||
| * "root_field_1.root_field_2.nested_field_1" : [ | ||
| * { | ||
| * "inner_root_1.inner_root_2.nested_field_2" : [ | ||
| * { | ||
| * "leaf_field" : [ | ||
| * "abc2" | ||
| * ] | ||
| * So, start re-building the path until the right one is found, ie inner_root_1.inner_root_2...... | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When you were looking for the
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The SearchHit structure for a If we have to look for a field called |
||
| */ | ||
| while (values == null) { | ||
| pathElement += "." + pathIterator.next(); | ||
| values = elements.get(pathElement); | ||
| } | ||
| } | ||
| value = ((Map<String, Object>) values.get(0)).get(fieldName.substring(hitName.length() + 1)); | ||
| } else { | ||
| value = field.getValues(); | ||
| } | ||
| return value; | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be common for both branches (needs changes to
extractNestedField) to make it more consistent. Something like:There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
extractNestedFieldcannot consistently return aDocumentFieldinstance so that we can call allwaysfield.getValues()inextract(SearchHit)method. The data structure inside aDocumentFieldis more complex in the case of nested fields and it requires further exploration before obtaining an equivalent offield.getValues()(see https://github.com/elastic/elasticsearch/pull/69368/files#diff-099b1feb3ed943ecc359be919a1dd67423938b9b8252e43c9ddd0a72027c1c87R120-R143).