Lucene: подстановочный знак не соответствует номеру после точки - PullRequest
0 голосов
/ 08 ноября 2018

Я недавно обновился с Lucene 3 до Lucene 6, и в v6 я обнаружил, что подстановочный знак ? больше не соответствует числам, следующим за точками. Вот пример:

строка для соответствия: a.1a

запрос: a.?a

В этом примере запрос соответствует строке в Lucene 3, но не в Lucene 6. С другой стороны, запрос a* соответствует и в Lucene 3, и в 6. Дальнейшее тестирование показывает, что эта разница в поведении возникает только тогда, когда за точкой следует число. Кстати, я использую StandardAnalyzer в Lucene 3 и 6.

Кто-нибудь знает, что здесь происходит? Как я могу восстановить поведение Lucene 3 или, в качестве альтернативы, адаптировать мой запрос Lucene 6, чтобы он соответствовал запросам Lucene 3?

UPDATE

Фрагмент кода Lucene 6.6 по запросу.

public List<ResultDocument> search(String queryString)
        throws SearchException, CheckedOutOfMemoryError {
    stopped =false;

    QueryWrapper queryWrapper = createQuery(queryString);
    Query query = queryWrapper.query;
    boolean isPhraseQuery = queryWrapper.isPhraseQuery;

    readLock.lock();
    try {
        checkIndexesExist();

        DelegatingCollector collector= new DelegatingCollector(){
            @Override
            public void collect(int doc) throws IOException {
                leafDelegate.collect(doc);
                if(stopped){
                    throw new StoppedSearcherException();
                }
            }
        };
        collector.setDelegate(TopScoreDocCollector.create(MAX_RESULTS, null));
        try{
            luceneSearcher.search(query, collector);
        }
        catch (StoppedSearcherException e){}
        ScoreDoc[] scoreDocs = ((TopScoreDocCollector)collector.getDelegate()).topDocs().scoreDocs;

        ResultDocument[] results = new ResultDocument[scoreDocs.length];
        for (int i = 0; i < scoreDocs.length; i++) {
            Document doc = luceneSearcher.doc(scoreDocs[i].doc);
            float score = scoreDocs[i].score;
            LuceneIndex index = indexes.get(((DecoratedMultiReader) luceneSearcher.getIndexReader()).decoratedReaderIndex(i));
            IndexingConfig config = index.getConfig();
            results[i] = new ResultDocument(
                doc, score, query, isPhraseQuery, config, fileFactory,
                outlookMailFactory);
        }
        return Arrays.asList(results);
    }
    catch (IllegalArgumentException e) {
        throw wrapEmptyIndexException(e);
    }
    catch (IOException e) {
        throw new SearchException(e.getMessage());
    }
    catch (OutOfMemoryError e) {
        throw new CheckedOutOfMemoryError(e);
    }
    finally {
        readLock.unlock();
    }
}

Дополнительный код:

private static QueryWrapper createQuery(String queryString)
        throws SearchException {
    PhraseDetectingQueryParser queryParser = new PhraseDetectingQueryParser(
        Fields.CONTENT.key(), IndexRegistry.getAnalyzer());
    queryParser.setAllowLeadingWildcard(true);
    RewriteMethod rewriteMethod = MultiTermQuery.SCORING_BOOLEAN_REWRITE;
    queryParser.setMultiTermRewriteMethod(rewriteMethod);

    try {
        Query query = queryParser.parse(queryString);
        boolean isPhraseQuery = queryParser.isPhraseQuery();
        return new QueryWrapper(query, isPhraseQuery);
    }
    catch (IllegalArgumentException e) {
        throw new SearchException(e.getMessage());
    }
    catch (ParseException e) {
        throw new SearchException(e.getMessage());
    }
}

private static final class QueryWrapper {
    public final Query query;
    public final boolean isPhraseQuery;

    private QueryWrapper(Query query, boolean isPhraseQuery) {
        this.query = query;
        this.isPhraseQuery = isPhraseQuery;
    }
}

Еще больше кода:

public final class PhraseDetectingQueryParser extends QueryParser {

    /*
     * This class is used for determining whether the parsed query is supported
     * by the fast-vector highlighter. The latter only supports queries that are
     * a combination of TermQuery, PhraseQuery and/or BooleanQuery.
     */

    private boolean isPhraseQuery = true;

    public PhraseDetectingQueryParser(  String defaultField,
                                        Analyzer analyzer) {
        super(defaultField, analyzer);
    }

    public boolean isPhraseQuery() {
        return isPhraseQuery;
    }

    protected Query newFuzzyQuery(  Term term,
                                    float minimumSimilarity,
                                    int prefixLength) {
        isPhraseQuery = false;
        return super.newFuzzyQuery(term, minimumSimilarity, prefixLength);
    }

    protected Query newMatchAllDocsQuery() {
        isPhraseQuery = false;
        return super.newMatchAllDocsQuery();
    }

    protected Query newPrefixQuery(Term prefix) {
        isPhraseQuery = false;
        return super.newPrefixQuery(prefix);
    }

    protected Query newWildcardQuery(org.apache.lucene.index.Term t) {
        isPhraseQuery = false;
        return super.newWildcardQuery(t);
    }

}

1 Ответ

0 голосов
/ 22 января 2019

StandardAnalyzer разбивает входные данные на термины за период (если только по обе стороны от него нет буквы или цифры по обе стороны от него). Таким образом, это разделяет это на два термина: «а» и «1а»

Поскольку вы используете запрос с подстановочными знаками, в конце запроса не выполняется никакого анализа, поэтому он не получает токены, и в индексе нет терминов, соответствующих запросу. Если вам нужно искать «1a», без подстановочных знаков или чего-либо еще, вы должны найти этот документ.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...