Как можно построить запрос, который будет искать как точные фразы, так и фразы с опечатками? Я застрял на этом и похоже, что я двигаюсь в неправильном направлении.
Например, у меня есть следующее поле в моем запросе edismax:
q=apple iphone
Это работает, но теперь мне нужно сделать его более терпимым к опечаткам. Я обновляю свой запрос, и теперь он возвращает те же результаты, что и раньше, даже когда пользователь вводит ошибки:
q=aple~2 iphane~2
Далее я обнаружил, что теперь точное совпадение запроса не всегда находится на первой странице (например, у меня действительно есть продукт 'aple iphane'). Итак, я добавляю точный запрос, используя условие «ИЛИ». Теперь мой запрос выглядит так
q=(aple~2 iphane~2) OR 'aple iphane'^3
Проблема в том, что теперь он возвращает только точное совпадение и больше не возвращает нечеткие записи. Что я делаю неправильно?
Вот полный запрос:
http://localhost:8983/solr/test/select?omitHeader=true
&q=(aple~2 iphane~2) OR 'aple iphane'^3
&start=0
&rows=30
&fl=*,score
&fq=itemType:"Product"
&defType=edismax
&qf=title_de^1000 title_de_ranked^1000 description_de^1 category_name_de^50 brand^15 merchant_name^80 uniuque_values^10000 searchable_attribute_product.name^1000 searchable_attribute_product.description.short^100 searchable_attribute_product.description.long^100 searchable_attribute_mb.book.author^500
&mm=90
&pf=title_de^2000 description_de^2
&ps=1
&qs=2
&boost=category_boost
&mm.autoRelax=true
&wt=json
&json.nl=flat
У меня есть ошибка в запросе, или я выбрал совершенно неправильный способ?
Эту фразу я хочу найти в 'title_de', все остальные поля второстепенны. Вот тип поля из моей схемы:
<fieldType name="text_de_ngram" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_de.txt" />
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
<filter class="solr.GermanNormalizationFilterFactory"/>
<filter class="solr.GermanLightStemFilterFactory"/>
<filter class="solr.NGramFilterFactory" minGramSize="2" maxGramSize="25"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
<filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_de.txt" />
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
<filter class="solr.GermanNormalizationFilterFactory"/>
<filter class="solr.GermanLightStemFilterFactory"/>
<filter class="solr.SnowballPorterFilterFactory" language="German" />
</analyzer>
</fieldType>
Спасибо!
UPD: Я обнаружил, что мой запрос (q=(aple~2 iphane~2) ИЛИ 'aple iphane'^3) неверен, поэтому я нашел, как построить 2 других запроса, которые работают лучше, вы можете их увидеть в конце поста. Я до сих пор не знаю, почему они дают разные результаты, потому что оператором по умолчанию для запроса SOLR является «ИЛИ», поэтому «термин1 ИЛИ термин2 ИЛИ термин3 ИЛИ термин4» должен быть таким же, как «(термин1 ИЛИ термин2) ИЛИ (термин3 ИЛИ термин4).< /em>
По предложению @Persimmonium я добавляю несколько отладочных примеров, чтобы показать, как работают нечеткие запросы для edismax (но не всегда ожидаемые). Я обнаружил, что «apple iphone» — не лучший пример в моем большом и немецком языковом индексе, поэтому я использовал в качестве примера продукт с названием «Samsung Magic Info-Lite».
Вот все параметры моего запроса:
"params":{
"mm":"100%",
"q":"samsung magic",
"defType":"edismax",
"indent":"on",
"qf":"title_de",
"fl":"*,score",
"pf":"title_de",
"wt":"json",
"debugQuery":"on",
"_":"1501409530601"
}
Итак, этот запрос возвращает мне правильные продукты (у меня есть 6 продуктов с обоими этими словами в поле title_de). После того, как я добавлю опечатки к обоим словам:
"q":"somsung majic"
Товары не найдены.
Затем я добавляю нечеткие операторы к обоим словам:
"q":"somsung~2 majic~2"
Найдено 6 товаров. Вот результат отладочного запроса:
"debug":{
"rawquerystring":"somsung~2 majic~2",
"querystring":"somsung~2 majic~2",
"parsedquery":"(+(DisjunctionMaxQuery((title_de:somsung~2)) DisjunctionMaxQuery((title_de:majic~2)))~2 DisjunctionMaxQuery((title_de:\"somsung 2 majic 2\")))/no_coord",
"parsedquery_toString":"+(((title_de:somsung~2) (title_de:majic~2))~2) (title_de:\"somsung 2 majic 2\")",
"explain":{
"69019":"\n1.3424492 = sum of:\n 1.3424492 = sum of:\n 1.1036766 = sum of:\n 0.26367697 = weight(title_de:amsung in 305456) [ClassicSimilarity], result of:\n 0.26367697 = score(doc=305456,freq=1.0), product of:\n 0.073149204 = queryWeight, product of:\n 0.6666666 = boost\n 7.209292 = idf, computed as log((docCount+1)/(docFreq+1)) + 1 from:\n 635.0 = docFreq\n 316313.0 = docCount\n 0.015219777 = queryNorm\n 3.604646 = fieldWeight in 305456, product of:\n 1.0 = tf(freq=1.0), with freq of:\n 1.0 = termFreq=1.0\n 7.209292 = idf, computed as log((docCount+1)/(docFreq+1)) + 1 from:\n 635.0 = docFreq\n 316313.0 = docCount\n 0.5 = fieldNorm(doc=305456)\n 0.2373093 = weight(title_de:msung in 305456) [ClassicSimilarity], result of:\n 0.2373093 = score(doc=305456,freq=1.0), product of:\n 0.06583429 = queryWeight, product of:\n 0.6 = boost\n 7.209292 = idf, computed as log((docCount+1)/(docFreq+1)) + 1 from:\n 635.0 = docFreq\n 316313.0 = docCount\n 0.015219777 = queryNorm\n 3.604646 = fieldWeight in 305456, product of:\n 1.0 = tf(freq=1.0), with freq of:\n 1.0 = termFreq=1.0\n 7.209292 = idf, computed as log((docCount+1)/(docFreq+1)) + 1 from:\n 635.0 = docFreq\n 316313.0 = docCount\n 0.5 = fieldNorm(doc=305456)\n 0.26367697 = weight(title_de:samsun in 305456) [ClassicSimilarity], result of:\n 0.26367697 = score(doc=305456,freq=1.0), product of:\n 0.073149204 = queryWeight, product of:\n 0.6666666 = boost\n 7.209292 = idf, computed as log((docCount+1)/(docFreq+1)) + 1 from:\n 635.0 = docFreq\n 316313.0 = docCount\n 0.015219777 = queryNorm\n 3.604646 = fieldWeight in 305456, product of:\n 1.0 = tf(freq=1.0), with freq of:\n 1.0 = termFreq=1.0\n 7.209292 = idf, computed as log((docCount+1)/(docFreq+1)) + 1 from:\n 635.0 = docFreq\n 316313.0 = docCount\n 0.5 = fieldNorm(doc=305456)\n 0.33901328 = weight(title_de:samsung in 305456) [ClassicSimilarity], result of:\n 0.33901328 = score(doc=305456,freq=1.0), product of:\n 0.094048984 = queryWeight, product of:\n 0.85714287 = boost\n 7.209292 = idf, computed as log((docCount+1)/(docFreq+1)) + 1 from:\n 635.0 = docFreq\n 316313.0 = docCount\n 0.015219777 = queryNorm\n 3.604646 = fieldWeight in 305456, product of:\n 1.0 = tf(freq=1.0), with freq of:\n 1.0 = termFreq=1.0\n 7.209292 = idf, computed as log((docCount+1)/(docFreq+1)) + 1 from:\n 635.0 = docFreq\n 316313.0 = docCount\n 0.5 = fieldNorm(doc=305456)\n 0.23877257 = sum of:\n 0.23877257 = weight(title_de:magic in 305456) [ClassicSimilarity], result of:\n 0.23877257 = score(doc=305456,freq=1.0), product of:\n 0.0762529 = queryWeight, product of:\n 0.8 = boost\n 6.262649 = idf, computed as log((docCount+1)/(docFreq+1)) + 1 from:\n 1638.0 = docFreq\n 316313.0 = docCount\n 0.015219777 = queryNorm\n 3.1313245 = fieldWeight in 305456, product of:\n 1.0 = tf(freq=1.0), with freq of:\n 1.0 = termFreq=1.0\n 6.262649 = idf, computed as log((docCount+1)/(docFreq+1)) + 1 from:\n 1638.0 = docFreq\n 316313.0 = docCount\n 0.5 = fieldNorm(doc=305456)\n",
},
"QParser":"ExtendedDismaxQParser"
}
Такое поведение меня устраивает, пока у меня нет реального продукта с названием Somsung majic. Это теоретическая ситуация, но на практике есть много других неверных результатов поиска, вызванных этими нечеткими операторами.
Итак, чтобы справиться с такими вещами, моя идея заключалась в том, как я описал изначально, чтобы добавить точную запись (без нечетких модификаторов) с повышающим коэффициентом. Итак, теперь вопрос, как это будет лучше реализовано. Я обнаружил, что этот запрос работает приемлемо, если я уменьшу параметр mm:
"q":"somsung~2 majic~2 somsung^3 majic^3"
Это потому, что я добавляю больше слов в запрос, поэтому «минимум должен совпадать» также необходимо уменьшить. Проблема в том, что при уменьшении «мм» я получаю плохие результаты для длинных заголовков с точным вводом заголовка (некоторые неправильные элементы могут быть оценены выше из-за других факторов). Это отладка для него:
"debug":{
"rawquerystring":"somsung~2 majic~2 somsung^3 majic^3",
"querystring":"somsung~2 majic~2 somsung^3 majic^3",
"parsedquery":"(+(DisjunctionMaxQuery((title_de:somsung~2)) DisjunctionMaxQuery((title_de:majic~2)) DisjunctionMaxQuery((title_de:somsung))^3.0 DisjunctionMaxQuery((title_de:majic))^3.0)~2 DisjunctionMaxQuery((title_de:\"somsung 2 majic 2 somsung 3 majic 3\")))/no_coord",
"parsedquery_toString":"+(((title_de:somsung~2) (title_de:majic~2) ((title_de:somsung))^3.0 ((title_de:majic))^3.0)~2) (title_de:\"somsung 2 majic 2 somsung 3 majic 3\")",
"explain":{
"69019":"\n0.3418829 = sum of:\n 0.3418829 = product of:\n 0.6837658 = sum of:\n 0.5621489 = sum of:\n 0.13430178 = weight(title_de:amsung in 305456) [ClassicSimilarity], result of:\n 0.13430178 = score(doc=305456,freq=1.0), product of:\n 0.037257966 = queryWeight, product of:\n 0.6666666 = boost\n 7.209292 = idf, computed as log((docCount+1)/(docFreq+1)) + 1 from:\n 635.0 = docFreq\n 316313.0 = docCount\n 0.0077520725 = queryNorm\n 3.604646 = fieldWeight in 305456, product of:\n 1.0 = tf(freq=1.0), with freq of:\n 1.0 = termFreq=1.0\n 7.209292 = idf, computed as log((docCount+1)/(docFreq+1)) + 1 from:\n 635.0 = docFreq\n 316313.0 = docCount\n 0.5 = fieldNorm(doc=305456)\n 0.12087161 = weight(title_de:msung in 305456) [ClassicSimilarity], result of:\n 0.12087161 = score(doc=305456,freq=1.0), product of:\n 0.033532172 = queryWeight, product of:\n 0.6 = boost\n 7.209292 = idf, computed as log((docCount+1)/(docFreq+1)) + 1 from:\n 635.0 = docFreq\n 316313.0 = docCount\n 0.0077520725 = queryNorm\n 3.604646 = fieldWeight in 305456, product of:\n 1.0 = tf(freq=1.0), with freq of:\n 1.0 = termFreq=1.0\n 7.209292 = idf, computed as log((docCount+1)/(docFreq+1)) + 1 from:\n 635.0 = docFreq\n 316313.0 = docCount\n 0.5 = fieldNorm(doc=305456)\n 0.13430178 = weight(title_de:samsun in 305456) [ClassicSimilarity], result of:\n 0.13430178 = score(doc=305456,freq=1.0), product of:\n 0.037257966 = queryWeight, product of:\n 0.6666666 = boost\n 7.209292 = idf, computed as log((docCount+1)/(docFreq+1)) + 1 from:\n 635.0 = docFreq\n 316313.0 = docCount\n 0.0077520725 = queryNorm\n 3.604646 = fieldWeight in 305456, product of:\n 1.0 = tf(freq=1.0), with freq of:\n 1.0 = termFreq=1.0\n 7.209292 = idf, computed as log((docCount+1)/(docFreq+1)) + 1 from:\n 635.0 = docFreq\n 316313.0 = docCount\n 0.5 = fieldNorm(doc=305456)\n 0.17267373 = weight(title_de:samsung in 305456) [ClassicSimilarity], result of:\n 0.17267373 = score(doc=305456,freq=1.0), product of:\n 0.047903106 = queryWeight, product of:\n 0.85714287 = boost\n 7.209292 = idf, computed as log((docCount+1)/(docFreq+1)) + 1 from:\n 635.0 = docFreq\n 316313.0 = docCount\n 0.0077520725 = queryNorm\n 3.604646 = fieldWeight in 305456, product of:\n 1.0 = tf(freq=1.0), with freq of:\n 1.0 = termFreq=1.0\n 7.209292 = idf, computed as log((docCount+1)/(docFreq+1)) + 1 from:\n 635.0 = docFreq\n 316313.0 = docCount\n 0.5 = fieldNorm(doc=305456)\n 0.12161691 = sum of:\n 0.12161691 = weight(title_de:magic in 305456) [ClassicSimilarity], result of:\n 0.12161691 = score(doc=305456,freq=1.0), product of:\n 0.038838807 = queryWeight, product of:\n 0.8 = boost\n 6.262649 = idf, computed as log((docCount+1)/(docFreq+1)) + 1 from:\n 1638.0 = docFreq\n 316313.0 = docCount\n 0.0077520725 = queryNorm\n 3.1313245 = fieldWeight in 305456, product of:\n 1.0 = tf(freq=1.0), with freq of:\n 1.0 = termFreq=1.0\n 6.262649 = idf, computed as log((docCount+1)/(docFreq+1)) + 1 from:\n 1638.0 = docFreq\n 316313.0 = docCount\n 0.5 = fieldNorm(doc=305456)\n 0.5 = coord(2/4)\n"
},
"QParser":"ExtendedDismaxQParser"
}
Этот запрос работает даже с большим параметром «мм» (например, 90%):
"q":"(somsung~2 majic~2) OR (somsung^3 majic^3)"
Но проблема в том, что я получаю 430 результатов (вместо 6 желаемых). Вот отладка с примером неправильного продукта:
"debug":{
"rawquerystring":"(somsung~2 majic~2) OR (somsung^3 majic^3)",
"querystring":"(somsung~2 majic~2) OR (somsung^3 majic^3)",
"parsedquery":"(+((DisjunctionMaxQuery((title_de:somsung~2)) DisjunctionMaxQuery((title_de:majic~2))) (DisjunctionMaxQuery((title_de:somsung))^3.0 DisjunctionMaxQuery((title_de:majic))^3.0))~1 DisjunctionMaxQuery((title_de:\"somsung 2 majic 2 somsung 3 majic 3\")))/no_coord",
"parsedquery_toString":"+((((title_de:somsung~2) (title_de:majic~2)) (((title_de:somsung))^3.0 ((title_de:majic))^3.0))~1) (title_de:\"somsung 2 majic 2 somsung 3 majic 3\")",
"explain":{
"113746":"\n0.1275867 = sum of:\n 0.1275867 = product of:\n 0.2551734 = sum of:\n 0.2551734 = product of:\n 0.5103468 = sum of:\n 0.5103468 = sum of:\n 0.26860356 = weight(title_de:losung in 296822) [ClassicSimilarity], result of:\n 0.26860356 = score(doc=296822,freq=1.0), product of:\n 0.037257966 = queryWeight, product of:\n 0.6666666 = boost\n 7.209292 = idf, computed as log((docCount+1)/(docFreq+1)) + 1 from:\n 635.0 = docFreq\n 316313.0 = docCount\n 0.0077520725 = queryNorm\n 7.209292 = fieldWeight in 296822, product of:\n 1.0 = tf(freq=1.0), with freq of:\n 1.0 = termFreq=1.0\n 7.209292 = idf, computed as log((docCount+1)/(docFreq+1)) + 1 from:\n 635.0 = docFreq\n 316313.0 = docCount\n 1.0 = fieldNorm(doc=296822)\n 0.24174322 = weight(title_de:osung in 296822) [ClassicSimilarity], result of:\n 0.24174322 = score(doc=296822,freq=1.0), product of:\n 0.033532172 = queryWeight, product of:\n 0.6 = boost\n 7.209292 = idf, computed as log((docCount+1)/(docFreq+1)) + 1 from:\n 635.0 = docFreq\n 316313.0 = docCount\n 0.0077520725 = queryNorm\n 7.209292 = fieldWeight in 296822, product of:\n 1.0 = tf(freq=1.0), with freq of:\n 1.0 = termFreq=1.0\n 7.209292 = idf, computed as log((docCount+1)/(docFreq+1)) + 1 from:\n 635.0 = docFreq\n 316313.0 = docCount\n 1.0 = fieldNorm(doc=296822)\n 0.5 = coord(1/2)\n 0.5 = coord(1/2)\n"
},
"QParser":"ExtendedDismaxQParser"
}
Итак, хотя я получил лучшие результаты, мне все еще нужно улучшить поиск, и я до сих пор не знаю, какой способ выбрать и почему я получаю такие результаты.