在ElasticSearch中从数组中删除元素/对象,然后进行匹配查询

zf2sa74q  于 2024-01-06  发布在  ElasticSearch
关注(0)|答案(4)|浏览(194)

我在尝试从elasticsearch中的数组中删除元素/对象时遇到了问题。
这是索引的Map:

  1. {
  2. "example1": {
  3. "mappings": {
  4. "doc": {
  5. "properties": {
  6. "locations": {
  7. "type": "geo_point"
  8. },
  9. "postDate": {
  10. "type": "date"
  11. },
  12. "status": {
  13. "type": "long"
  14. },
  15. "user": {
  16. "type": "text",
  17. "fields": {
  18. "keyword": {
  19. "type": "keyword",
  20. "ignore_above": 256
  21. }
  22. }
  23. }
  24. }
  25. }
  26. }
  27. }
  28. }

字符串
这是一个示例文档。

  1. {
  2. "_index": "example1",
  3. "_type": "doc",
  4. "_id": "8036",
  5. "_score": 1,
  6. "_source": {
  7. "user": "kimchy8036",
  8. "postDate": "2009-11-15T13:12:00",
  9. "locations": [
  10. [
  11. 72.79887719999999,
  12. 21.193036000000003
  13. ],
  14. [
  15. -1.8262150000000001,
  16. 51.178881999999994
  17. ]
  18. ]
  19. }
  20. }


使用下面的查询,我可以添加多个位置。

  1. POST /example1/_update_by_query
  2. {
  3. "query": {
  4. "match": {
  5. "_id": "3"
  6. }
  7. },
  8. "script": {
  9. "lang": "painless",
  10. "inline": "ctx._source.locations.add(params.newsupp)",
  11. "params": {
  12. "newsupp": [
  13. -74.00,
  14. 41.12121
  15. ]
  16. }
  17. }
  18. }


但是我不能从位置中删除数组对象。我已经尝试了下面的查询,但它不起作用。

  1. POST example1/doc/3/_update
  2. {
  3. "script": {
  4. "lang": "painless",
  5. "inline": "ctx._source.locations.remove(params.tag)",
  6. "params": {
  7. "tag": [
  8. -74.00,
  9. 41.12121
  10. ]
  11. }
  12. }
  13. }


请让我知道我在这里做错了什么。我使用的是弹性版本5.5.2

jyztefdp

jyztefdp1#

在轻松的脚本中,Array.remove()方法通过索引而不是值来删除。
下面是一个在Elasticsearch脚本中通过值删除数组元素的工作示例:

  1. POST objects/_update_by_query
  2. {
  3. "query": {
  4. ... // use regular ES query to remove only in relevant documents
  5. },
  6. "script": {
  7. "source": """
  8. if (ctx._source[params.array_attribute] != null) {
  9. for (int i=ctx._source[params.array_attribute].length-1; i>=0; i--) {
  10. if (ctx._source[params.array_attribute][i] == params.value_to_remove) {
  11. ctx._source[params.array_attribute].remove(i);
  12. }
  13. }
  14. }
  15. """,
  16. "params": {
  17. "array_attribute": "<NAME_OF_ARRAY_PROPERTY_TO_REMOVE_VALUE_IN>",
  18. "value_to_remove": "<VALUE_TO_REMOVE_FROM_ARRAY>",
  19. }
  20. }
  21. }

字符串
如果你的脚本只需要从一个特定的数组属性中删除值,你可能需要简化脚本。例如,从文档的.color_list数组中删除"green"

  1. _doc/001 = {
  2. "color_list": ["red", "blue", "green"]
  3. }


删除"green"的脚本:

  1. POST objects/_update_by_query
  2. {
  3. "query": {
  4. ... // use regular ES query to remove only in relevant documents
  5. },
  6. "script": {
  7. "source": """
  8. for (int i=ctx._source.color_list.length-1; i>=0; i--) {
  9. if (ctx._source.color_list[i] == params.color_to_remove) {
  10. ctx._source.color_list.remove(i);
  11. }
  12. }
  13. """,
  14. "params": {
  15. "color_to_remove": "green"
  16. }
  17. }
  18. }

展开查看全部
bqjvbblv

bqjvbblv2#

add()不同,remove()获取元素的索引并将其删除。
painless中的ctx._source.locations是一个ArrayList,它有Listremove()方法:
E remove(int index)
在列表中指定的位置添加元素(可选操作).
其他方法见无痛API -列表。
参见this answer示例代码。

wb1gzix0

wb1gzix03#

  1. "script" : {
  2. "lang":"painless",
  3. "inline":"ctx._source.locations.remove(params.tag)",
  4. "params":{
  5. "tag":indexToRemove
  6. }
  7. }

字符串
如果使用ctx._source.locations.add(elt)添加元素,则使用ctx._source.locations.remove(indexToRemove)删除数组中元素的索引。

kd3sttzy

kd3sttzy4#

  1. POST /your_index/_update_by_query
  2. {
  3. "script": {
  4. "source": "ctx._source.your_array.removeIf(item -> item == params.value)",
  5. "lang": "painless",
  6. "params": {
  7. "value": "value_to_remove"
  8. }
  9. },
  10. "query": {
  11. "term": {
  12. "your_array": "value_to_remove"
  13. }
  14. }
  15. }

字符串

相关问题