Удалить элемент из результата массива

У меня такой результат

 {
    "_index": "products-1479727033119",
    "_type": "product",
    "_id": "123",
    "_score": 5.2519913,
    "_source": {
      "name": "Samsung S7",
      "rating": 4.5123123,
      "id": "609126",
      "stores": [
        {
            "id" :123214,
            "name":"Walmart"
        },
        {
            "id" :2141251,
            "name":"ebay"
        }
      ],
    }
  }

В некоторых случаях мне нужно, чтобы мой результат был таким же, однако мне нужно фильтровать элементы массива

И результат должен быть такой:

{
    "_index": "products-1479727033119",
    "_type": "product",
    "_id": "123",
    "_score": 5.2519913,
    "_source": {
      "name": "Samsung S7",
      "rating": 4.5123123,
      "id": "609126",
      "stores": [
        {
            "id" :123214,
            "name":"Walmart"
        }
      ],
    }
  }

Возможно ли это в одном запросе?

1 ответ

  1. да, необходимо просмотреть вложенные объекты в elasticsearch. Необходимо определить сопоставления в схеме для вложенных объектов. После настройки схемы для поддержки вложенных объектов в исходном документе можно использовать вложенные фильтры innerhits.

    Используйте следующие сопоставления схемы для документа.

    -XPut "localhost:9200/products/product/_mapping"
        {
            "product": {
                "_source": {
                    "enabled": true
                },
                "properties": {
                    "stores": {
                        "type": "nested",
                        "properties": {
                            "id": {
                                "type": "string",
                                "index": "analyzed"
                            },
                            "name": {
                                "type": "string",
                                "index": "analyzed"
                            }
                        }
                    },
                    "name": {
                        "type": "string",
                        "index": "analyzed"
                    },
    
                    "rating": {
                        "type": "integer"
                    },
                    "id": {
                        "type": "integer"
                    }
                }
            }
        }
    

    Теперь ваш usecase может включать или не включать фильтрацию родительского документа, но так как вам необходимо фильтровать вложенные документы, чтобы соответствовать некоторым критериям, вы можете использовать вложенные фильтры/запрос с innerhits. Innerhits in elasticsearch возвращает внутренний вложенный документ, соответствующий вложенному запросу.

    предположим оба случая-

    a) не фильтровать Родительский документ —

    {
        "query": {
            "filtered": {
                "query": {
                    "bool": {
                        "must": [{
                            "nested": {
                                "path": "stores",
                                "query": {
                                    "filtered": {
                                        "query": {
                                            "bool": {
                                                "must": [{
                                                    "term": {
                                                        "stores.name": {
                                                            "value": "nokia"
                                                        }
                                                    }
                                                }]
                                            }
                                        }
                                    }
                                },
                                "inner_hits":{}
                            }
                        }]
                    }
                }
            }
        }
    }
    

    B) фильтровать как родительские, так и вложенные объекты —

    {
        "query": {
            "filtered": {
                "query": {
                    "bool": {
                        "must": [
                          {"term": {
                            "name": {
                              "value": "samsung"
                            }
                          }},
                          {
                            "nested": {
                                "path": "stores",
                                "query": {
                                    "filtered": {
                                        "query": {
                                            "bool": {
                                                "must": [{
                                                    "term": {
                                                        "stores.name": {
                                                            "value": "nokia"
                                                        }
                                                    }
                                                }]
                                            }
                                        }
                                    }
                                },
                                "inner_hits":{}
                            }
                        }]
                    }
                }
            }
        }
    }
    

    В случае b также можно использовать фильтр для родительского документа.

    Innerhits ответ —

       {
      "took": 6,
      "timed_out": false,
      "_shards": {
        "total": 5,
        "successful": 5,
        "failed": 0
      },
      "hits": {
        "total": 1,
        "max_score": 2.122635,
        "hits": [
          {
            "_index": "nested",
            "_type": "product",
            "_id": "AVmYrzR0isULrG9L5jlr",
            "_score": 2.122635,
            "_source": {
              "name": "Samsung S7",
              "rating": 4.5123123,
              "id": "609126",
              "stores": [
                {
                  "id": 123214,
                  "name": "Walmart"
                },
                {
                  "id": 898989,
                  "name": "nokia"
                },
                {
                  "id": 67676,
                  "name": "nokia"
                }
              ]
            },
            "inner_hits": {
              "stores": {
                "hits": {
                  "total": 2,
                  "max_score": 1.8472979,
                  "hits": [
                    {
                      "_index": "nested",
                      "_type": "product",
                      "_id": "AVmYrzR0isULrG9L5jlr",
                      "_nested": {
                        "field": "stores",
                        "offset": 2
                      },
                      "_score": 1.8472979,
                      "_source": {
                        "id": 67676,
                        "name": "nokia"
                      }
                    },
                    {
                      "_index": "nested",
                      "_type": "product",
                      "_id": "AVmYrzR0isULrG9L5jlr",
                      "_nested": {
                        "field": "stores",
                        "offset": 1
                      },
                      "_score": 1.8472979,
                      "_source": {
                        "id": 898989,
                        "name": "nokia"
                      }
                    }
                  ]
                }
              }
            }
          }
        ]
      }
    }
    

    Как вы можете видеть в объекте ответа, inner_hits выходит дополнительный объект json вместе с исходным документом, innerhits JSON объект содержит массив всех отфильтрованных вложенных документов, которые соответствуют «nokia» как имя.

    Вы получаете то, что вы попросили форму, но в другом формате/структуре данных. Вы можете позже написать переводчик уровня API, сериализатор модели, чтобы проанализировать ответ в надлежащем формате, который вы хотите, чтобы ваш клиент(браузер/приложение) требовал

    Пожалуйста, обратитесь к elastic innerhits doc для получения дополнительной информации.

    Надеюсь, это поможет
    Спасибо