问题描述
以下简单的ES Groovy脚本使用带有订单数据(orderItem)的python字典,并将其附加到Elasticsearch中的订单列表中。所有orderItems的列表然后驻留在_source.Orders
script:if(ctx._source.containsKey(\ Orders \)){ctx._source.Orders + = orderItem;} else {ctx._source.Orders = [orderItem]};
params:{orderItem:orderItem}
在我的用例中,订单来自不同的商店,希望他们进入_source.Orders下的列表结构.Shop5Hgk,_source.Orders.Shop86hG,_source.Orders.Shop5G60等商店名称是动态的。
无论如何,我尝试,ES抛出异常抱怨订单显然是空的。
So, what is the right groovy syntax to create the Orders field first, and then the field for the shop name and then append orderItems to that?
Update: Full python function with (not working)
def updateLastOrdersElasticsearch(self,data):
es = elasticsearch.Elasticsearch(timeout=500)
actions = []
for shopName,orderList in data.items():
for orderItem in orderList:
sku = orderItem['SKU']
action = {
"_index": "myindex",
"script": "if (ctx._source.containsKey(\"Orders\")) {if (ctx._source.containsKey(shopName)){ctx._source.Orders."+shopName+" += Orders;}} else {ctx._source.Orders = []; ctx._source.Orders."+shopName+" = [Orders]}; ctx._source.TimestampUpdated = TimestampUpdated",
"_type": "items",
'_op_type': 'update',
"_id": sku,
"params":{"shopName":shopName,"Orders": orderItem, "TimestampUpdated":datetime.now().isoformat()}
}
actions.append(action)
return helpers.bulk(es, actions)
I think that initially your _source.Orders
field is null, i.e. not even an empty array.
Moreover, containsKey
might not be the right way to go, because your _source
might contain a field named Orders
whose type might not be an array, i.e. it might be a dynamic object standing for an existing order, or worse, just a plain string.
I suggest you try a different approach by first checking if Orders
is null and initialize it to an empty array if not. Then you can append the orderItem
to the resulting array:
{
"script" : "ctx._source.Orders = ((ctx._source.Orders ?: []) += orderItem)",
"params" : {
"orderItem" : orderItem
}
}
An alternative to this would be to simply ensure that when you index your document the first time, you make sure that the Orders
field is initialized with an empty array []
and then your script could simply append orderItems
to that array.
UPDATE
Based on your comments, I'm revising my answer in order to deal with the case where Orders
is a dynamic object containing shop names as keys and each of those keys points to an array of orders for that shop. It's basically the same idea as earlier, just that we need to deal with one more level (i.e. the shop names).
First the script makes sure that the Orders
object exists and then it makes sure that the shop array within the Orders
object exists as well. All that remains to do is to append the orderItem
to the shop array:
{
"script" : "ctx._source.Orders = ctx._source.Orders ?: [shopName:'']; ctx._source.Orders[shopName] = ((ctx._source.Orders[shopName] ?: []) + orderItem); ctx._source.TimestampUpdated = TimestampUpdated",
"params" : {
"shopName": shopName,
"orderItem" : orderItem,
"TimestampUpdated":datetime.now().isoformat()
}
}
这篇关于用于生成嵌套字段的弹性搜索Groovy脚本语法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!