Elasticsearch 多级嵌套对象过滤和更新
Elasticsearch multilevel nested object filter and update
弹性搜索:6.3
我正在尝试通过过滤特定书籍来更新嵌套字段。以下是示例记录。
{
"StoreName":"test",
"StoreID":"12435",
"BookInfo":[
{
"Name":"Book1",
"Comments":[
{
"date":"2019-01-07",
"Comment":"this is a nice book"
},
{
"date":"2019-01-06",
"Comment":"this is a nice book"
},
{
"date":"2019-01-04",
"Comment":"this is a nice book"
},
{
"date":"2019-01-03",
"Comment":"this is a nice book"
}
],
"UPC":2435466,
},
{
"Name":"Book2",
"Comments":[
{
"date":"2019-01-07",
"Comment":"this is a nice book"
},
{
"date":"2019-01-06",
"Comment":"this is a nice book"
},
{
"date":"2019-01-04",
"Comment":"this is a nice book"
},
{
"date":"2019-01-03",
"Comment":"this is a nice book"
}
],
"UPC":576868345657,
},
}
]
}
在这里,我们有多个商店,每个商店都有多本书。对于每本书,我们每天都会存储用户评论。我想通过检查该特定日期的评论是否已经存在,在 [BookInfo.Comments] 下添加日期和评论。如果它已经存在,那么我将需要跳过它,如果没有则附加新评论。
我尝试通过更新 API 来做到这一点,但我无法过滤特定书籍并从可用书籍列表中更新评论。有人可以帮我弄这个吗?提前致谢。
请参阅下文,查看您的相关文档,我如何创建映射、通过查询脚本进行更新以及响应如何显示。
映射:
PUT mybook
{
"mappings": {
"mydocs":{
"properties":{
"StoreName": {
"type": "keyword"
},
"StoreID":{
"type": "keyword"
},
"BookInfo":{
"type": "nested",
"properties": {
"Comments" :{
"type": "nested",
"properties":{
"date":{
"type": "date"
},
"Comment": {
"type": "text"
}
}
},
"Name": {
"type": "keyword"
}
}
}
}
}
}
}
查询:
以下是您需要的Update By Query:
POST mybook/_update_by_query
{
"query": {
"bool": {
"must": [
{
"term": {
"StoreName": "test"
}
},
{
"term": {
"StoreID": "12435"
}
},
{
"nested": {
"path": "BookInfo",
"query": {
"term": {
"BookInfo.Name": "Book1"
}
}
}
}
]
}
},
"script": {
"lang": "painless",
"inline": """
ArrayList list = ctx._source.BookInfo;
for(int i=0; i<list.size();i++){
HashMap myHashMap = list.get(i);
boolean isPresent = false;
for(int j=0; j<myHashMap.size();j++){
String mybook = myHashMap.get(params.book_key);
if(mybook==params.book_value)
{
ArrayList mylist = myHashMap.get("Comments");
for(int k=0; k<mylist.size(); k++){
HashMap existingMap = mylist.get(k);
Iterator entries = existingMap.entrySet().iterator();
while(entries.hasNext()){
Map.Entry entry = (Map.Entry) entries.next();
if(entry.getKey()==params.date_key && entry.getValue()==params.date_value){
isPresent = true
}
}
}
if(!isPresent){
HashMap myMap = new HashMap();
myMap.put(params.date_key, params.date_value);
myMap.put(params.comment_key, params.comment_value);
mylist.add(myMap);
isPresent = false;
}
}
}
}
""",
"params": {
"book_key": "Name",
"book_value": "Book1",
"date_key": "date",
"date_value": "2019-01-08",
"comment_key": "Comment",
"comment_value": "This is a new comment here"
}}
}
总而言之,我正在尝试为具有 "Name:Book1"
、"StoreId": "1234"
和 "StoreName": "test"
的书添加日期和评论
注意查询中的以下部分:
"params": {
"book_key": "Name",
"book_value": "Book1",
"date_key": "date",
"date_value": "2019-01-08",
"comment_key": "Comment",
"comment_value": "This is a new comment here"
}
这些是您需要将上述查询(根据您的要求)修改为 运行 的参数。
其余的无痛脚本是我建议您完成的,因为它就像普通 java 代码一样,我只是从 BookInfo
遍历它以达到所需document/fields 并添加 date/comment
.
当然,请原谅我使用了这么多的迭代和循环。我建议更好的方法是在您的应用程序层中完全构建文档并 re-ingest 它。
回复:
{
"_index": "mybook",
"_type": "mydocs",
"_id": "1",
"_version": 44,
"found": true,
"_source": {
"StoreName": "test",
"StoreID": "12435",
"BookInfo": [
{
"Comments": [
{
"date": "2019-01-07",
"Comment": "this is a nice book"
},
{
"date": "2019-01-06",
"Comment": "this is a nice book"
},
{
"date": "2019-01-04",
"Comment": "this is a nice book"
},
{
"date": "2019-01-03",
"Comment": "this is a nice book"
},
{
"date": "2019-01-08",
"Comment": "This is a new comment here"
}
],
"UPC": 2435466,
"Name": "Book1"
},
{
"Comments": [
{
"date": "2019-01-07",
"Comment": "this is a nice book"
},
{
"date": "2019-01-06",
"Comment": "this is a nice book"
},
{
"date": "2019-01-04",
"Comment": "this is a nice book"
},
{
"date": "2019-01-03",
"Comment": "this is a nice book"
}
],
"UPC": 576868345657,
"Name": "Book2"
}
]
}
}
希望对您有所帮助!
弹性搜索:6.3
我正在尝试通过过滤特定书籍来更新嵌套字段。以下是示例记录。
{
"StoreName":"test",
"StoreID":"12435",
"BookInfo":[
{
"Name":"Book1",
"Comments":[
{
"date":"2019-01-07",
"Comment":"this is a nice book"
},
{
"date":"2019-01-06",
"Comment":"this is a nice book"
},
{
"date":"2019-01-04",
"Comment":"this is a nice book"
},
{
"date":"2019-01-03",
"Comment":"this is a nice book"
}
],
"UPC":2435466,
},
{
"Name":"Book2",
"Comments":[
{
"date":"2019-01-07",
"Comment":"this is a nice book"
},
{
"date":"2019-01-06",
"Comment":"this is a nice book"
},
{
"date":"2019-01-04",
"Comment":"this is a nice book"
},
{
"date":"2019-01-03",
"Comment":"this is a nice book"
}
],
"UPC":576868345657,
},
}
]
}
在这里,我们有多个商店,每个商店都有多本书。对于每本书,我们每天都会存储用户评论。我想通过检查该特定日期的评论是否已经存在,在 [BookInfo.Comments] 下添加日期和评论。如果它已经存在,那么我将需要跳过它,如果没有则附加新评论。 我尝试通过更新 API 来做到这一点,但我无法过滤特定书籍并从可用书籍列表中更新评论。有人可以帮我弄这个吗?提前致谢。
请参阅下文,查看您的相关文档,我如何创建映射、通过查询脚本进行更新以及响应如何显示。
映射:
PUT mybook
{
"mappings": {
"mydocs":{
"properties":{
"StoreName": {
"type": "keyword"
},
"StoreID":{
"type": "keyword"
},
"BookInfo":{
"type": "nested",
"properties": {
"Comments" :{
"type": "nested",
"properties":{
"date":{
"type": "date"
},
"Comment": {
"type": "text"
}
}
},
"Name": {
"type": "keyword"
}
}
}
}
}
}
}
查询:
以下是您需要的Update By Query:
POST mybook/_update_by_query
{
"query": {
"bool": {
"must": [
{
"term": {
"StoreName": "test"
}
},
{
"term": {
"StoreID": "12435"
}
},
{
"nested": {
"path": "BookInfo",
"query": {
"term": {
"BookInfo.Name": "Book1"
}
}
}
}
]
}
},
"script": {
"lang": "painless",
"inline": """
ArrayList list = ctx._source.BookInfo;
for(int i=0; i<list.size();i++){
HashMap myHashMap = list.get(i);
boolean isPresent = false;
for(int j=0; j<myHashMap.size();j++){
String mybook = myHashMap.get(params.book_key);
if(mybook==params.book_value)
{
ArrayList mylist = myHashMap.get("Comments");
for(int k=0; k<mylist.size(); k++){
HashMap existingMap = mylist.get(k);
Iterator entries = existingMap.entrySet().iterator();
while(entries.hasNext()){
Map.Entry entry = (Map.Entry) entries.next();
if(entry.getKey()==params.date_key && entry.getValue()==params.date_value){
isPresent = true
}
}
}
if(!isPresent){
HashMap myMap = new HashMap();
myMap.put(params.date_key, params.date_value);
myMap.put(params.comment_key, params.comment_value);
mylist.add(myMap);
isPresent = false;
}
}
}
}
""",
"params": {
"book_key": "Name",
"book_value": "Book1",
"date_key": "date",
"date_value": "2019-01-08",
"comment_key": "Comment",
"comment_value": "This is a new comment here"
}}
}
总而言之,我正在尝试为具有 "Name:Book1"
、"StoreId": "1234"
和 "StoreName": "test"
注意查询中的以下部分:
"params": {
"book_key": "Name",
"book_value": "Book1",
"date_key": "date",
"date_value": "2019-01-08",
"comment_key": "Comment",
"comment_value": "This is a new comment here"
}
这些是您需要将上述查询(根据您的要求)修改为 运行 的参数。
其余的无痛脚本是我建议您完成的,因为它就像普通 java 代码一样,我只是从 BookInfo
遍历它以达到所需document/fields 并添加 date/comment
.
当然,请原谅我使用了这么多的迭代和循环。我建议更好的方法是在您的应用程序层中完全构建文档并 re-ingest 它。
回复:
{
"_index": "mybook",
"_type": "mydocs",
"_id": "1",
"_version": 44,
"found": true,
"_source": {
"StoreName": "test",
"StoreID": "12435",
"BookInfo": [
{
"Comments": [
{
"date": "2019-01-07",
"Comment": "this is a nice book"
},
{
"date": "2019-01-06",
"Comment": "this is a nice book"
},
{
"date": "2019-01-04",
"Comment": "this is a nice book"
},
{
"date": "2019-01-03",
"Comment": "this is a nice book"
},
{
"date": "2019-01-08",
"Comment": "This is a new comment here"
}
],
"UPC": 2435466,
"Name": "Book1"
},
{
"Comments": [
{
"date": "2019-01-07",
"Comment": "this is a nice book"
},
{
"date": "2019-01-06",
"Comment": "this is a nice book"
},
{
"date": "2019-01-04",
"Comment": "this is a nice book"
},
{
"date": "2019-01-03",
"Comment": "this is a nice book"
}
],
"UPC": 576868345657,
"Name": "Book2"
}
]
}
}
希望对您有所帮助!