2012-05-15 8 views
6

¿Es posible usar un Lucene SpanQuery para encontrar todas las ocurrencias donde los términos "rojo", "verde" y "azul" aparecen dentro de una sola oración?Búsqueda consciente de la oración con Lucene SpanQueries

Mi primer enfoque (incompleto/incorrecto) es escribir un analizador que coloca un token de marcador de oraciones especial y el comienzo de una oración en la misma posición que la primera palabra de la oración y luego buscar algo similar al siguientes:

SpanQuery termsInSentence = new SpanNearQuery(
    SpanQuery[] { 
    new SpanTermQuery(new Term (MY_SPECIAL_SENTENCE_TOKEN)), 
    new SpanTermQuery(new Term ("red")), 
    new SpanTermQuery(new Term ("green")), 
    new SpanTermQuery(new Term ("blue")), 
    }, 
    999999999999, 
    false 
); 

SpanQuery nextSentence = new SpanTermQuery(new Term (MY_SPECIAL_SENTENCE_TOKEN)); 

SpanNotQuery notInNextSentence = new SpanNotQuery(termsInSentence,nextSentence); 

el problema, por supuesto, es que nextSentence no es realmente la próxima frase, es cualquier marcador de sentencia, incluyendo el de la frase que termsInSentence partidos. Por lo tanto, esto no funcionará.

Mi próximo enfoque es crear el analizador que coloca la ficha antes de la oración (es decir, antes de la primera palabra en lugar de en la misma posición que la primera palabra). El problema con esto es que luego tengo que dar cuenta de la compensación extra causada por MY_SPECIAL_SENTENCE_TOKEN. Es más, esto será especialmente malo al principio cuando estoy usando un patrón ingenuo para dividir oraciones (por ejemplo, dividir en /\.\s+[A-Z0-9]/) porque tendré que dar cuenta de todos los marcadores de oraciones (falsas) cuando busco USS Enterprise.

Entonces ... ¿cómo debo abordar esto?

Respuesta

1

Me gustaría indexar cada oración como un documento de Lucene, incluyendo un campo que marca el origen de la oración. Dependiendo de su material fuente, la sobrecarga de la oración/LuceneDoc puede ser aceptable.

0

En realidad, parece que está bastante cerca de la solución. Creo que indexar una bandera de final de frase es un buen enfoque. El problema es que su bandera de fin de oración está en su SpanNearQuery, que es lo que lo está tirando. Le está pidiendo que encuentre un lapso que contenga y no contiene contiene MY_SPECIAL_SENTENCE_TOKEN. La consulta se contradice a sí misma, por lo que, por supuesto, no encontrará ninguna coincidencia. Lo que realmente necesita saber es que los tres términos ("rojo", "verde" y "azul") ocurren en un lapso que no se superpone con MY_SPECIAL_SENTENCE_TOKEN (es decir, el token de oración no aparece entre esos condiciones).

Además, la falta de nombres de campo en las Term ctors sería un problema, pero Lucene debe lanzar una excepción quejándose de que, por lo que supongo que no es el verdadero problema aquí. Podría ser que la versión de Lucene en el momento en que se escribió esto no se quejó de los campos no coincidentes en SpanNears, por lo que quizás valga la pena mencionarlo.

Esto parece funcionar para mí:

SpanQuery termsInSentence = new SpanNearQuery(
    new SpanQuery[] { 
     new SpanTermQuery(new Term ("text", "red")), 
     new SpanTermQuery(new Term ("text", "green")), 
     new SpanTermQuery(new Term ("text", "blue")), 
    }, 
    9999, 
    false 
); 

SpanQuery nextSentence = new SpanTermQuery(new Term ("text", MY_SPECIAL_SENTENCE_TOKEN)); 

SpanQuery notInNextSentence = new SpanNotQuery(termsInSentence,nextSentence); 

En cuanto a dónde dividir frases, en lugar de utilizar el enfoque de expresiones regulares ingenuo, me gustaría probar usando java.text.Breakiterator. No es perfecto, pero hace un trabajo bastante bueno.

Cuestiones relacionadas