0

我使用 StandardAnalyzer 创建了一个具有以下三个字段的 Lucene 索引。

  1. 街道名称
  2. 城市
  3. 状态

我正在使用下面的包装类来简化编写布尔查询

public interface IQuery
    {
        BooleanQuery GetQuery();
    }
public class QueryParam : IQuery
{
    public string[] Fields { get; set; }
    public string Term { get; set; }        
    private BooleanQuery _indexerQuery;                    
    public QueryParam(string term, params string[] fields)
    {
        Term = term;
        Fields = fields;
    }        
    public BooleanQuery GetQuery()
    {
        _indexerQuery = new BooleanQuery();
        foreach (var field in Fields)
            _indexerQuery.Add(new FuzzyQuery(new Term(field, Term)), Occur.SHOULD);
        return _indexerQuery;
    }
}
public class AndQuery : IQuery
{
    private readonly IList<IQuery> _queryParams = new List<IQuery>();        
    private BooleanQuery _indexerQuery;
    public AndQuery(params IQuery[] queryParams)
    {
        foreach (var queryParam in queryParams)
        {
            _queryParams.Add(queryParam);
        }
    }    
    public BooleanQuery GetQuery()
    {
        _indexerQuery = new BooleanQuery();
        foreach (var query in _queryParams)
            _indexerQuery.Add(query.GetQuery(), Occur.MUST);
        return _indexerQuery;
    }
}
public class OrQuery : IQuery
{
    private readonly IList<IQuery> _queryParams = new List<IQuery>();
    private readonly BooleanQuery _indexerQuery = new BooleanQuery();
    public OrQuery(params IQuery[] queryParams)
    {
        foreach (var queryParam in queryParams)
        {
            _queryParams.Add(queryParam);
        }
    }
    public BooleanQuery GetQuery()
    {
        foreach (var query in _queryParams)
            _indexerQuery.Add(query.GetQuery(), Occur.SHOULD);
        return _indexerQuery;
    }
    public OrQuery AddQuery(IQuery query)
    {
        _queryParams.Add(query);
        return this;
    }
}

下面的查询在 Lucene.Net 中没有给我任何结果,但是当我在 Luke 中搜索相同的查询时,它可以完美运行。

var query = new AndQuery(new QueryParam(city.ToLower(), "city"), new QueryParam(state.ToLower(), "state"), new QueryParam(streetAddress.ToLower(), "streetname"));

执行query.GetQuery()给了我下面的结果查询。

{+(城市:坦帕~0.5)+(州:佛罗里达州~0.5)+(街道:网球场~0.5)}

4

2 回答 2

1

您可以使用 BooleanQuery 进行搜索。用段中的空格打破您的术语,然后在索引中创建查询和搜索。

前任:-


BooleanQuery booleanQuery = new BooleanQuery()
BooleanQuery searchTermQuery = new BooleanQuery();
foreach (var searchTerm in searchTerms)
{
    var searchTermSegments = searchTerm.Split(new[] { " " }, StringSplitOptions.RemoveEmptyEntries);
    if (searchTermSegments.Count() > 1)
    {
        searchTermQuery.Clauses().Clear();
        foreach (var SegTex in searchTermSegments)
        {
            searchTermQuery.Add( new FuzzyQuery(new Term("FieldName", SegTex.ToLower().Trim())),BooleanClause.Occur.MUST);
        }
        booleanQuery.Add(searchTermQuery, BooleanClause.Occur.MUST);
    }
    else
    {
        booleanQuery.Add(new FuzzyQuery(new Term("FieldName", searchTerm.ToLower().Trim())), BooleanClause.Occur.MUST);
    }
}
于 2013-06-06T06:09:17.517 回答
0

问题在于治疗tennis court。您还没有展示如何索引这些字段,但我会假设它们在索引中被标记化,StandardAnalyzer例如使用 a 之类的东西。这意味着,“网球场”将分为两个单独的术语“网球场”和“球场”。但是,在手动创建 FuzzyQuery 时,没有分析或标记化,因此您将只有一个术语“网球场”。“网球场”与“网球”(6 次编辑)或“球场”(7 次编辑)之间的编辑距离很大,因此两者都不匹配。

这里令人困惑的一个原因似乎是

+(city:tampa~0.5) +(state:fl~0.5) +(street:tennis court~0.5)

似乎工作。然而,假设用于调试的文本查询输出可以通过查询解析器运行以生成相同的查询是不安全的,这是一个很好的例子。QueryParser语法根本无法表达您可以使用手动构建的查询执行的所有操作。通过查询解析器运行该查询将生成一个查询,更像:

+(city:tampa~0.5) +(state:fl~0.5) +((street:tennis) (defaultField:court~0.5))

哪个会找到匹配项,因为我们可以预期它会找到city:tampa, state:fl, 和street:tennis(请参阅此 Lucene 查询解析器文档部分以获取解释查询解析器此行为的另一个示例)。我不知道它是否在默认字段中找到匹配court项,但实际上并不需要。

APhraseQuery是在 Lucene 查询中将多个术语(单词)串在一起的典型方式(这看起来像street:"tennis court"在解析的查询中)。

于 2013-06-05T15:33:11.853 回答