/ / Elasticsearch Fuzzy Phrases - elasticsearch

Elasticsearch Fuzzy Phrases - elasticsearch

Mam następujące zapytanie, aby dodać rozmycie do mojegoSzukaj. Teraz jednak zdaję sobie sprawę, że zapytanie pasujące nie uwzględnia kolejności słów w ciągu wyszukiwania, podobnie jak wyrażenie match_frase. Nie mogę jednak uzyskać wyrażenia match, aby uzyskać dziwne wyniki. Czy istnieje sposób, aby powiedzieć dopasowanie, aby uwzględnić kolejność i odległość między słowami?

{
"query": {
"match": {
"content": {
"query": "some search terms like this",
"fuzziness": 1,
"operator": "and"
}
}
}
}

Odpowiedzi:

9 dla odpowiedzi № 1

W końcu zorientowałem się, że muszę użyć kombinacji span zapytania, które zapewniają doskonałą precyzję do rozmycia i wpadki. Musiałem dodać funkcję, aby ręcznie tokenizować moje frazy i dodać programowo tablicę „klauzul”:

{"query":
{
"span_near": {
"clauses": [
{
"span_multi": {
"match": {
"fuzzy": {
"content": {
"fuzziness": "2",
"value": "word"
}
}
}
}
},
{
"span_multi": {
"match": {
"fuzzy": {
"content": {
"fuzziness": "2",
"value": "another"
}
}
}
}
}
],
"slop": 1,
"in_order": "true"

1 dla odpowiedzi nr 2

@econgineer Excellent post.

Chciałem wypróbować to w zapytaniu ES, nad którym pracujemy - ale jestem zbyt leniwy, aby nadal robić dane JSON ....

Myślę, że ten kod działa ... co dziwne, powoduje, że jq narzeka, ale działa ElasticSearch ....

import json
import pprint
from collections import defaultdict
nested_dict = lambda: defaultdict(nested_dict)
query=nested_dict()
query["span_near"]["clauses"]=list()
query["slop"]="1"
query["in_order"]="true"


words=["what","is","this"]
for w in words:
nest = nested_dict()
nest["span_multi"]["match"]["fuzzy"]["msg"]["fuzziness"]["value"]=w
nest["span_multi"]["match"]["fuzzy"]["msg"]["fuzziness"]["fuzziness"]="2"
json.dumps(nest)
query["span_near"]["clauses"].append(json.loads(json.dumps(nest)))


pprint.pprint(json.loads(json.dumps(query)))

Jeśli upiększysz wynik za pomocą

cat t2.json | tr  """ """  | jq "."

Powinieneś zobaczyć coś takiego

{
"in_order": "true",
"slop": "1",
"span_near": {
"clauses": [
{
"span_multi": {
"match": {
"fuzzy": {
"msg": {
"fuzziness": {
"fuzziness": "2",
"value": "what"
}
}
}
}
}
},
{
"span_multi": {
"match": {
"fuzzy": {
"msg": {
"fuzziness": {
"fuzziness": "2",
"value": "is"
}
}
}
}
}
},
{
"span_multi": {
"match": {
"fuzzy": {
"msg": {
"fuzziness": {
"fuzziness": "2",
"value": "this"
}
}
}
}
}
}
]
}
}

A potem zapytanie ES jest normalne

curl --silent My_ES_Server:9200:/INDEX/_search -d @t2.json

Bardzo dziękuję za wstępne wskazówki, mam nadzieję, że ktoś inny znajdzie zastosowanie.


0 dla odpowiedzi № 3

Rzeczywiście, doskonałe pytanie i odpowiedź. Jestem zaskoczony, że to „rozmyte dopasowanie do wyrażenia” nie ma wsparcia po wyjęciu z pudełka.

Oto przetestowany kod NodeJS, który generuje rozmyty blok zapytania o dopasowaniu do wyrażenia (klauzula wielokrotna) w kontekście wyszukiwania wielokrotnego (msearch), ale powinien działać tak samo z jednym wyszukiwaniem.

Stosowanie:

let queryBody = [];
client.msearch({
body: queryBody
})

queryBody.push({ index: "YOUR_INDEX" });
queryBody.push(createESFuzzyPhraseQueryBlock("YOUR PHRASE", "YOUR_FIELD_NAME", 2));   // 2 <- fuzziness

Funkcje:

const createESFuzzyPhraseClauseBlock = (word, esFieldName, fuzziness) => {
let clauseBlock = JSON.parse(
`{
"span_multi": {
"match": {
"fuzzy": {
"${esFieldName}": {
"fuzziness": "${fuzziness}",
"value": "${word}"
}
}
}
}
}`);

return clauseBlock;
};


const createESFuzzyPhraseQueryBlock = (phrase, esFieldName, fuzziness) => {
let clauses = [];

let words = phrase.split(" ");
words.forEach(word => clauses.push(createESFuzzyPhraseClauseBlock(word, esFieldName, fuzziness)));

let queryBlock =
{
"query":
{
"span_near": {
"clauses": clauses,
"slop": 1,
"in_order": "true"
}
}
};

return queryBlock;
};