как вернуть все документы, которые имеют подмножество входного массива в OpenSearch

У меня есть документ с заданной структурой:

      { "name" : "WF1", "myIndex" : [3, 4, 5] }

Допустим, у меня есть 4 таких записи -

      { "name" : "WF1", "myIndex" : [3, 4, 5] }
{ "name" : "WF2", "myIndex" : [6, 7, 8] }
{ "name" : "WF3", "myIndex" : [9, 10, 11] }
{ "name" : "WF4", "myIndex" : [3, 6, 9] }

Если я стреляю ниже запроса «термин»:

      GET myIndex/_search
{
  "query": {
    "terms": {
      "qualsIndex": [
        3, 6, 9, 20
      ]
    }
  }
}

Он возвращает все 4 записи. Принимая во внимание, что я хочу вернуть только запись с 3,6, 9, т.е. только WF4. По сути, мне нужен результирующий документ, в котором передано подмножество входных данных.

Примечание. Я могу настроить структуру своего документа, чтобы добиться этого. возможно ли это в OpenSearch?

2 ответа

TLD;

Вы можете добиться этого с помощью запроса набора терминов .

Чтобы понять

Пример сопоставления:

      {
  "mappings": {
    "properties": {
      "name": {
        "type": "keyword"
      },
      "myIndex": {
        "type": "keyword"
      },
      "required_matches": {
        "type": "long"
      }
    }
  }
}

Пример запроса:

      {
  "query": {
    "terms_set": {
      "myIndex": {
        "terms": [3, 6, 9, 20],
        "minimum_should_match_field": "required_matches"
      }
    }
  }
}

В твоем случае, required_matchesдолжен быть индексирован как количество элементов массива myIndex.

Воспроизвести

Вот полностью рабочий пример:

Прежде всего установка:

      DELETE /72004393/

PUT /72004393/
{
  "mappings": {
    "properties": {
      "myIndex": {
        "type": "keyword"
      },
      "name": {
        "type": "text"
      }
    }
  }
}

POST _bulk
{"index":{"_index":"72004393"}}
{"name":"WF1","myIndex":["3","4","5"]}
{"index":{"_index":"72004393"}}
{"name":"WF2","myIndex":["6","7","8"]}
{"index":{"_index":"72004393"}}
{"name":"WF3","myIndex":["9","10","11"]}
{"index":{"_index":"72004393"}}
{"name":"WF4","myIndex":["3","6","9"]}

Запрос:

      GET /72004393/_search
{
  "query": {
    "terms_set": {
      "myIndex": {
        "terms": [ "3", "6", "9", "20" ],
        "minimum_should_match_script": {
          "source": "3"
        }
      }
    }
  }
}

Дает:

      {
  ...
  "hits" : {
  ...
    "max_score" : 2.859232,
    "hits" : [
      {
        "_index" : "72004393",
        "_id" : "LqOQZ4ABOgujegeQ2gfV",
        "_score" : 2.859232,
        "_source" : {
          "name" : "WF4",
          "myIndex" : ["3","6","9"]
        }
      }
    ]
  }
}

Другой пример:

      PUT test
{
  "mappings": {
    "properties": {
      "myIndex": {
        "type": "keyword"
      },
      "name": {
        "type": "text"
      },
      "required_matches": {
        "type": "long"
      }
    }
  }
}
      POST _bulk
{"index":{"_index":"test"}}
{"name":"WF1","myIndex":["3","4","5"], "required_matches": 3} 
{"index":{"_index":"test"}}
{"name":"WF2","myIndex":["6","7","8"], "required_matches": 3}
{"index":{"_index":"test"}}
{"name":"WF3","myIndex":["9","10","11"], "required_matches": 3}
{"index":{"_index":"test"}}
{"name":"WF4","myIndex":["3","6","9"], "required_matches": 3}
{"index":{"_index":"test"}}
{"name":"WF5","myIndex":["3","6","9", "15", "20"], "required_matches": 5}
{"index":{"_index":"test"}}
{"name":"WF6","myIndex":["3","6","9", "15"], "required_matches": 4}

Запрос:

      GET test/_search
{
  "query": {
    "terms_set": {
      "myIndex": {
        "terms": ["3", "6", "9"],
        "minimum_should_match_field": "required_matches"
      }
    }
  }
}

Приведенный выше запрос будет соответствовать только WF4, поскольку его required_match равен 3, а требуемые совпадения WF5 И WF6 — 4 и 5.

Если вы обновите термины в запросе на ["3", "6", "9", "15"]он будет соответствовать как WF4, так и WF5, и если вы обновите его до ["3", "6", "9", "15", "20"]он будет соответствовать WF4, WF5, WF6.

TLDR;

Насколько мне известно, ни в ElasticSearch, ни в OpenSearch нет решения. Но я думаю, вы можете взломать его, используя numberв качестве words

Взлом

Индексация документа с полем myIndexв виде строки чисел. Позже я могу найти эти числа, используя запрос соответствия и такой параметр, как minimum_should_match.

      DELETE 72004393

POST _bulk
{"index":{"_index":"72004393"}}
{"name":"WF1","myIndex":"3 4 5"}
{"index":{"_index":"72004393"}}
{"name":"WF2","myIndex":"6 7 8"}
{"index":{"_index":"72004393"}}
{"name":"WF3","myIndex":"9 10 11"}
{"index":{"_index":"72004393"}}
{"name":"WF4","myIndex":"3 6 9"}


GET /72004393/_search
{
  "query": {
    "match": {
      "myIndex": {
        "query": "3 6 9 20",
        "minimum_should_match": 3
        }
    }
  }
}

Даст вам что-то вроде этого:

      {
  ...
  "hits" : {
    ...
    "max_score" : 2.0794413,
    "hits" : [
      {
        "_index" : "72004393",
        "_id" : "xaMuYoABOgujegeQJgZr",
        "_score" : 2.0794413,
        "_source" : {
          "name" : "WF4",
          "myIndex" : "3 6 9"
        }
      }
    ]
  }
}

Это не идеально и может привести к некоторым крайним случаям, но это самое близкое к «решению», которое я мог бы найти.

Другие вопросы по тегам