Elasticsearch сопоставить один массив с другим массивом - PullRequest
1 голос
/ 30 марта 2020

Допустим, у меня есть два индекса kids и outings_for_kids со следующими данными

  • дети
[
  {
    "name": "little kid 1",
    "i_like":["drawing","teddybears"]
  },

]
  • развлечения для детей
[
  {
    "name": "Teddybear drawing fights with apples!",
    "for_kids_that_like":["apples","teddybears","drawing", "play outside games"]
  },
  {
    "name": "drawing and teddies!",
    "for_kids_that_like":["teddybears","drawing"]
  }
]

Я хочу найти экскурсию, в которой нравятся те же вещи, что нравится маленькому ребенку, 1 балл и меньший балл, если у него больше.

Маленький ребенок 1 не должен совпадать на 100% с первый выход. У него есть то, что хочет маленький ребенок 1, но у него больше, например, яблок, он должен соответствовать 50%. Это должно соответствовать 100% со вторым выходом.

1 Ответ

3 голосов
/ 07 апреля 2020

Это будет двухэтапный процесс:

  1. Получить значение i_like из индекса полей
  2. Использование i_like из шага 1 для запроса индекса выходных данных

    1. Использовать запрос терминов для сопоставления каждому значению
    2. Использовать скрипт для сравнения размера массива с количеством значений
    3. Использовать постоянную оценку, чтобы получить ту же оценку на основе индекса индекса

Запрос

GET outings/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "constant_score": {
            "filter": {
              "bool": {
                "must": [
                  {
                    "term": {
                      "for_kids_that_like": {
                        "value": "teddybears"
                      }
                    }
                  },
                  {
                    "term": {
                      "for_kids_that_like": {
                        "value": "drawing"
                      }
                    }
                  },
                  {
                    "script": {
                      "script": "doc['for_kids_that_like.keyword'].size()==2" --> replace 2 with size of elements searched
                    }
                  }
                ]
              }
            },
            "boost": 100
          }
        },
        {
          "constant_score": {
            "filter": {
              "bool": {
                "must": [
                  {
                    "term": {
                      "for_kids_that_like": {
                        "value": "teddybears"
                      }
                    }
                  },
                  {
                    "term": {
                      "for_kids_that_like": {
                        "value": "drawing"
                      }
                    }
                  },
                  {
                    "script": {
                      "script": "doc['for_kids_that_like.keyword'].size()>2"
                    }
                  }
                ]
              }
            },
            "boost": 50
          }
        }
      ]
    }
  }
}

Результат:

"hits" : [
      {
        "_index" : "outings",
        "_type" : "_doc",
        "_id" : "IH7tVHEBbLcSRUWr6wPj",
        "_score" : 100.0,
        "_source" : {
          "name" : "Teddybear drawing fights with apples!",
          "for_kids_that_like" : [
            "teddybears",
            "drawing"
          ]
        }
      },
      {
        "_index" : "outings",
        "_type" : "_doc",
        "_id" : "IX7zVHEBbLcSRUWrhgM9",
        "_score" : 50.0,
        "_source" : {
          "name" : "Teddybear drawing fights with apples!",
          "for_kids_that_like" : [
            "teddybears",
            "drawing",
            "apples"
          ]
        }
      }
    ]

Если вы просто хотите показать точные документы совпадений сверху, а затем частичные совпадения, тогда вам не нужно постоянный счет (должен работать запрос с поиском термина). По умолчанию точные совпадения получают более высокий балл

...