features - Marcador de Solr/Lucene
solr tutorial (4)
Actualmente estamos trabajando en una prueba de concepto para un cliente que usa Solr y hemos podido configurar todas las características que desean excepto la puntuación.
El problema es que quieren puntajes que hacen que los resultados caigan en pedazos:
- Cubo 1: coincidencia exacta en la categoría (puntaje = 4)
- Cubo 2: coincidencia exacta en el nombre (puntaje = 3)
- Cubo 3: partido parcial en la categoría (puntaje = 2)
- Cubo 4: coincidencia parcial en el nombre (puntaje = 1)
Lo primero que hicimos fue desarrollar una clase de similitud personalizada que devolviera la puntuación correcta según el campo y una coincidencia exacta o parcial.
El único problema ahora es que cuando un documento coincide tanto con la categoría como con el nombre, los puntajes se suman.
Ejemplo: buscar "restaurante" devuelve documentos en la categoría restaurante que también tienen la palabra restaurante en su nombre y así obtener un puntaje de 5 (4 + 1) pero solo deben obtener 4.
Supongo que para que esto funcione tendríamos que desarrollar una clase de puntuación personalizada, pero no tenemos idea de cómo incorporar esto en Solr. Otra opción es crear una implementación de SortField personalizada similar a RandomSortField ya presente en Solr.
Tal vez hay incluso una solución más simple que no conocemos.
Todas las sugerencias son bienvenidas!
Creo que el DisMaxRequestHandler de Solr puede hacer el truco para ti.
Aquí están la explicación de Hossman de la encuesta Dismax y Mark Miller de los analizadores de consultas .
El marcador es parte de las consultas de lucene a través del método de consulta ''peso''.
En resumen, el marco llama a Query.weight (..). Scorer (..). Mira esto
http://lucene.apache.org/java/2_4_0/api/org/apache/lucene/search/Query.html
http://lucene.apache.org/java/2_4_0/api/org/apache/lucene/search/Weight.html
http://lucene.apache.org/jva/2_4_0/api/org/apache/lucene/search/Scorer.html
Para usar su propia clase Query en Solr, deberá implementar su propio solr QueryParserPlugin que use su propio QParser que genere su consulta lucene previamente implementada. Luego puede usarlo en Solr especificado aquí:
http://wiki.apache.org/solr/SolrPlugins#QParserPlugin
Esta parte de la implementación debería ser simple ya que es solo un código de pegado.
¡Disfruta hackeando Solr!
Puede anular la lógica que utiliza el marcador de soldadura. Solr usa la clase DefaultSimilarity para calificar.
public class CustomSimilarity extends DefaultSimilarity {
public CustomSimilarity() {
super();
}
public float tf(int freq) {
//your code
return (float) 1.0;
}
public float idf(int docFreq, int numDocs) {
//your code
return (float) 1.0;
}
}
<similarity class="<your package name>.CustomSimilarity"/>
Puede consultar varios factores que afectan la puntuación aquí
Para su requerimiento, puede crear depósitos si su puntaje está en un rango específico. Lea también sobre el aumento de campo, el aumento de documentos, etc. Eso podría ser útil en su caso.
Gracias por las buenas respuestas de arriba. Solo agregue a ellos, después de configurar esto en Solr 4.2.1, que permite la similitud por campo. (Antes de Solr 4, solo podía modificar la similitud para todos los campos de forma global).
Digamos que queremos que Solr no use la frecuencia inversa del documento (idf) para un campo específico; deberíamos escribir nuestra propia Similitud personalizada para esto, como se mencionó anteriormente:
package com.mycompany.similarity;
import org.apache.lucene.search.similarities.DefaultSimilarity;
public class NoIDFSimilarity extends DefaultSimilarity
{
@Override
public float idf(long docFreq, long numDocs)
{
return 1.0f;
}
@Override
public String toString()
{
return "NoIDFSimilarity";
}
}
y luego en nuestro schema.xml define un nuevo tipo de campo como este:
<fieldType name="int_no_idf"
class="solr.TrieIntField"
precisionStep="0"
positionIncrementGap="0"
omitNorms="true">
<similarity class="com.mycompany.similarity.NoIDFSimilarity"/>
</fieldType>
y usarlo en un campo como este:
<field name="tag_id_no_idf"
type="int_no_idf"
indexed="true"
stored="false"
multiValued="true" />
Si hiciéramos solo esto, obtendría la siguiente excepción:
SEVERE: Unable to create core: SimilarList
org.apache.solr.common.SolrException: FieldType ''int_no_idf'' is configured with a similarity, but the global similarity does not support it: class org.apache.solr.search.similarities.DefaultSimilarityFactory
at org.apache.solr.schema.IndexSchema.readSchema(IndexSchema.java:466)
at org.apache.solr.schema.IndexSchema.<init>(IndexSchema.java:122)
at org.apache.solr.core.CoreContainer.createFromLocal(CoreContainer.java:1018)
at org.apache.solr.core.CoreContainer.create(CoreContainer.java:1051)
at org.apache.solr.core.CoreContainer$3.call(CoreContainer.java:634)
at org.apache.solr.core.CoreContainer$3.call(CoreContainer.java:629)
at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Apr 25, 2013 5:02:08 PM org.apache.solr.common.SolrException log
SEVERE: null:org.apache.solr.common.SolrException: Unable to create core: SimilarList
at org.apache.solr.core.CoreContainer.recordAndThrow(CoreContainer.java:1672)
at org.apache.solr.core.CoreContainer.create(CoreContainer.java:1057)
at org.apache.solr.core.CoreContainer$3.call(CoreContainer.java:634)
at org.apache.solr.core.CoreContainer$3.call(CoreContainer.java:629)
at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: org.apache.solr.common.SolrException: FieldType ''int_no_idf'' is configured with a similarity, but the global similarity does not support it: class org.apache.solr.search.similarities.DefaultSimilarityFactory
at org.apache.solr.schema.IndexSchema.readSchema(IndexSchema.java:466)
at org.apache.solr.schema.IndexSchema.<init>(IndexSchema.java:122)
at org.apache.solr.core.CoreContainer.createFromLocal(CoreContainer.java:1018)
at org.apache.solr.core.CoreContainer.create(CoreContainer.java:1051)
... 10 more
Una búsqueda en Google lo lleva a esto , así que simplemente agregue esta línea en su schema.xml, que se aplicará al resto de los campos:
<similarity class="solr.SchemaSimilarityFactory"/>
(Desde ese enlace: ¡Pero tenga en cuenta que coord y queryNorm (= 1.0f) no se implementan ahora, por lo que obtendrá puntuaciones diferentes para TF-IDF!)