motor - solr tutorial
Búsqueda de campo exacta con solr/lucene (2)
Tengo campo de texto Y para una consulta dada, quiero encontrar todos los documentos que contienen valores de campo indexados.
query.contains(document.field_name)
Ejemplos: 1. field_name: "ab" 2. field_name: "abc"
Para la consulta "abd", quiero encontrar solo el primer elemento.
Una forma no eficiente de hacer esto es básicamente generar todas las subcadenas de la consulta y el campo de índice como una cadena.
¿Es posible implementar tales requisitos en Solr usando la funcionalidad existen? Si no, ¿cuál es el algoritmo / forma más eficiente para hacer esto?
PD. Parece que AdWords de Google hace esa coincidencia para encontrar adiciones.
Creo que puede ser difícil hacer esto en una sola consulta de Solr. Si he entendido bien su pregunta, creo que lo que haría es utilizar la cadena de consulta, buscar cada símbolo por turno y comparar los resultados de búsqueda con la cadena de consulta inicial. Por ejemplo, supongamos que su cadena de consulta es "term1 term2 term3". Debería buscar cada uno de estos términos a su vez:
/solr/index/select?q=term1
Esto puede devolver lo siguiente:
term1 term2 term4
term1 term2
term1 term2 term3
Luego podría ejecutar una comparación con su consulta inicial ("term1 term2 term3") para ver si contiene cada resultado de búsqueda. Disculpas si lo anterior no es útil.
Esta es una forma de hacer lo que está pidiendo:
Tipo de campo
<fieldType name="exact" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="solr.KeywordTokenizerFactory"/>
<filter class="solr.WordDelimiterFilterFactory" splitOnCaseChange="0" splitOnNumerics="0" preserveOriginal="0" generateWordParts="0" catenateAll="1" />
</analyzer>
<analyzer type="query">
<tokenizer class="solr.KeywordTokenizerFactory"/>
<filter class="solr.WordDelimiterFilterFactory" splitOnCaseChange="0" splitOnNumerics="0" preserveOriginal="0" generateWordParts="1" catenateAll="0" />
<filter class="solr.ShingleFilterFactory" outputUnigrams="true" outputUnigramsIfNoShingles="true" tokenSeparator="" maxShingleSize="99"/>
</analyzer>
</fieldType>
Explicación:
El analizador de índice usa WordDelimiterFilterFactory
para dividir el valor del campo en palabras. Entonces, usando su ejemplo, ab
se divide en las palabras a
y b
, y abd
se divide en a
, b
y d
. Establecemos catenateAll="1"
y generateWordParts="0"
por lo que las palabras individuales se descartan, lo que da como resultado una sola palabra. a
y b
convierten en ab
y a
, b
y d
convierten en abd
.
El analizador de consultas es similar con diferencias menores. Dividimos el valor en palabras, excepto que no descartamos las palabras ni las concatenamos. En cambio, pasamos las palabras a ShingleFilterFactory
, que toma la a
y b
y devuelve a
, b
y ab
.
La razón por la que utilizamos tejas en lugar de concatenación es permitir que abc
coincida con ab
y bc
. Si desea que abc
solo coincida con abc
, configure catenateAll="1"
y elimine la fábrica de tejas.
Usando esta configuración, ab
solo coincidirá con a
, b
, y ab
(no abd
). Además, abc
coincidirá con a
, b
, c
, ab
, bc
y abc
. También se debe tener en cuenta que ab
coincidirá con ab
. Si algo de esto no es lo que desea, debe poder configurar las fábricas de filtros de palabras y guijarros para hacer exactamente lo que necesita.
EDITAR : las versiones anteriores de esta respuesta ponen valores mágicos para marcar el inicio y el final del valor. Resulta que eso es innecesario; solo concatenar los valores juntos es suficiente para evitar que ab
coincida con abd
.
EDIT 2 ( corrección del analizador de índice ): WhitespaceTokenizerFactory
debería haber sido KeywordTokenizerFactory
. Además, WordDelimiterFilterFactory
debe tener catenateAll="0"
.