Как мне объединить два запроса Lucene, используя OR? - PullRequest
5 голосов
/ 23 ноября 2011

Я бы хотел найти свой индекс по двум полям, которые называются «a» и «b». Мне выдаются запросы типа Freud -- theories of psychology, и я хочу выполнить следующий запрос:

(a="Freud" AND b="theories of psychology") OR (b="Freud" AND a="theories of psychology")

Как мне это сделать? Пока у меня есть Lucene, который строит две половины (firstHalf и secondHalf), используя MultiFieldQueryParser, затем я объединил их с

BooleanQuery combined = new BooleanQuery();
combined.add(firstHalf, BooleanClause.Occur.SHOULD);
combined.add(secondHalf, BooleanClause.Occur.SHOULD);

Но combined позволяет возвращать результаты там, где встречаются только «теории», а не «психология», где я определенно хочу оба термина. Похоже, что Lucene разделяет «теории психологии» на три слова и объединяет их индивидуально с ИЛИ. Как мне это предотвратить?

firstHalf выглядит так:

Query firstHalf = MultiFieldQueryParser.parse(Version.LUCENE_33,
         new String[]{"Freud", "theories of psychology"},
         new String[]{"a", "b"},
         new BooleanClause.Occur[]{BooleanClause.Occur.MUST, BooleanClause.Occur.MUST},
         analyzer);

, где analyzer - это просто StandardAnalyzer объект.

Ответы [ 3 ]

4 голосов
/ 29 ноября 2011

Сам разобрался, но теперь код значительно длиннее; если кто-нибудь знает более изящное решение, пожалуйста, напишите, и я с удовольствием вознагражу. :) (Хотя я скоро сделаю это методом ... но вот полная версия того, что происходит ...)

QueryParser parser = new QueryParser(Version.LUCENE_33, "a", analyzer);
parser.setDefaultOperator(QueryParser.AND_OPERATOR);
Query a_0 = parser.parse("Freud");
parser = new QueryParser(Version.LUCENE_33, "b", analyzer);
parser.setDefaultOperator(QueryParser.AND_OPERATOR);
Query b_1 = parser.parse("theories of psychology");

BooleanQuery firstHalf = new BooleanQuery();
firstHalf.add(a_0, BooleanClause.Occur.MUST);
firstHalf.add(b_1, BooleanClause.Occur.MUST);

parser = new QueryParser(Version.LUCENE_33, "b", analyzer);
parser.setDefaultOperator(QueryParser.AND_OPERATOR);
Query b_0 = parser.parse("Freud");
parser = new QueryParser(Version.LUCENE_33, "a", analyzer);
parser.setDefaultOperator(QueryParser.AND_OPERATOR);
Query a_1 = parser.parse("theories of psychology");

BooleanQuery secondHalf = new BooleanQuery();
secondHalf.add(b_0, BooleanClause.Occur.MUST);
secondHalf.add(a_1, BooleanClause.Occur.MUST);

BooleanQuery combined = new BooleanQuery();
combined.add(firstHalf, BooleanClause.Occur.SHOULD);
combined.add(secondHalf, BooleanClause.Occur.SHOULD);

Оказывается, SHOULD работает так, как мне нужно здесь. Надеюсь, кто-то найдет это полезным, и я не просто общаюсь сам с собой;)

2 голосов
/ 30 мая 2013

Я написал ниже класс для генерации цепных нечетких запросов, где термин должен быть найден по нескольким полям.Комбинированный запрос можно получить, вызвав метод GetQuery().

public class QueryParam
{
    public string[] Fields { get; set; }
    public string Term { get; set; }

    private QueryParam _andOperandSuffix;
    private QueryParam _orOperandSuffix;

    private readonly BooleanQuery _indexerQuery = new BooleanQuery();        

    public QueryParam(string term, params string[] fields)
    {
        Term = term;
        Fields = fields;
    }

    public QueryParam And(QueryParam queryParam)
    {
        _andOperandSuffix = queryParam;
        return this;
    }

    public QueryParam Or(QueryParam queryParam)
    {
        _orOperandSuffix = queryParam;
        return this;
    }

    public BooleanQuery GetQuery()
    {            
        foreach (var field in Fields)
            _indexerQuery.Add(new FuzzyQuery(new Term(field, Term)), Occur.SHOULD);

        if (_andOperandSuffix != null)
            _indexerQuery.Add(_andOperandSuffix.GetQuery(),Occur.MUST);

        if (_orOperandSuffix != null)
            _indexerQuery.Add(_orOperandSuffix.GetQuery(), Occur.SHOULD);

        return _indexerQuery;
    }

}

Пример:

var leftquery = new QueryParam("Freud", "a").And(new QueryParam("theories of psychology", "b"));
var rightquery = new QueryParam("Freud", "b").And(new QueryParam("theories of psychology", "a"));
var query = leftquery.Or(rightquery);            
2 голосов
/ 24 ноября 2011

Стандартный анализатор будет токенизироваться.Таким образом, запрос theories of psychology эквивалентен theories OR of OR psychology.

Если вы хотите выполнить поиск по фразе «теории психологии», используйте PhraseQuery или обратите внимание, что QueryParser по умолчанию будет интерпретировать кавычки как означающие фразу (т.е. изменить код на"\"theories of psychology\"").

И да, в некотором смысле Lucene не использует булеву логику, но она техническая и не очень важна здесь.

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