【问题标题】:Multiple Field Query handling in LuceneLucene 中的多字段查询处理
【发布时间】:2013-03-21 15:35:10
【问题描述】:

我在 Lucene 中编写了一个索引搜索器,它将搜索索引数据库中的多个字段。

实际上它将查询作为两个字符串,一个是title,另一个是cityname。

现在索引数据库有三个字段:title, address and city。

只有当标题匹配并且城市名称匹配时才会发生命中。为此,我在帖子的帮助下使用MultiFieldQuerySearcher 编写了以下搜索器代码:

public void searchdb(String myQuery, String myCity) throws Exception
{
    System.out.println("Searching in the database ...");
    String[] fields={"title","address","city"};
    MultiFieldQueryParser parser = new MultiFieldQueryParser(Version.LUCENE_CURRENT, fields, new StandardAnalyzer(Version.LUCENE_CURRENT));
    parser.setDefaultOperator(QueryParser.Operator.AND);
    if(!myQuery.toLowerCase().contains(myCity.toLowerCase()))
    {
        myQuery="title:"+myQuery+" "+"address:"+myQuery+" "+myCity+" "+"city:"+myCity;
    }
    Query query=parser.parse(myQuery);
    if (query instanceof BooleanQuery) 
    {
        BooleanClause.Occur[] flags ={BooleanClause.Occur.MUST,BooleanClause.Occur.SHOULD,BooleanClause.Occur.MUST};
        BooleanQuery booleanQuery = (BooleanQuery) query;
        BooleanClause[] clauses = booleanQuery.getClauses();
        System.out.println("Query="+booleanQuery.toString()+" and Number of clauses="+clauses.length);
        for (int i = 0; i < clauses.length; i++) 
        {
            clauses[i].setOccur(flags[i]);
        }
        Directory dir=FSDirectory.open(new File("demoIndex"));
        IndexSearcher searcher = new IndexSearcher(dir, true);
        TopDocs hits = searcher.search(booleanQuery, 20);
        searcher.close();
        dir.close();
        System.out.println("Number of hits="+hits.totalHits);
    }
}

但它运行不正常。

例如,如果查询是“必胜客”,城市是“孟买”,我希望仅在数据库的标题字段中搜索“必胜客”,而仅在数据库的城市字段中搜索孟买。

但它也在数据库的城市字段中找到“小屋”,因为语句 booleanQuery.toString() 的输出为“+title:pizza +(title :hut city:hut) +city:mumbai"。

结果在 for 循环中给出 index outOfBound 错误。

我是 Lucene 的新手。所以我正在寻求帮助来解决这个问题。

【问题讨论】:

  • 你能分享你的代码吗?

标签: lucene


【解决方案1】:

只有当我们想在多个字段中搜索相同的关键字时,我们才使用 MultiFieldQueryParser。

为了处理您的用例,您已经分别引用了 city-keyword 和 title-keyword 会更简单。尝试使用以下代码。

StandardAnalyzer analyzer = new StandardAnalyzer(Version.LUCENE_CURRENT);
// city query
QueryParser cityQP = new QueryParser(Version.LUCENE_CURRENT, "city", analyzer);
Query cityQuery = cityQP.parse(myCity);

// title query
QueryParser titleQP = new QueryParser(Version.LUCENE_CURRENT, "title", analyzer);
Query titleQuery = titleQP.parse(myQuery);

// final query
BooleanQuery finalQuery = new BooleanQuery();
finalQuery.add(cityQuery, Occur.MUST); // MUST implies that the keyword must occur.
finalQuery.add(titleQuery, Occur.MUST); // Using all "MUST" occurs is equivalent to "AND" operator.

【讨论】:

  • 但是先生有一个问题。在我的索引中有一个条目,其标题是“必胜客”,城市是“孟买”。当我查询标题为“Pizza”和城市“MUmbai”的索引时,点击次数结果为 0。但根据我的理解,它应该是 1,因为这两个术语都存在于其相应的字段中。你能解释一下吗?
  • 1) 确保在索引和查询时使用相同的分析器。--- 2) 请将最终查询打印到输出并粘贴到此处。---3) 使用 Luke检查您的索引。使用起来非常简单。它是一个用于探索和检查 Lucene 索引的 GUI 工具。使用 Luke 检查索引是否包含您期望的内容。---顺便说一句,请不要再“先生”了.. :)
  • 最终查询是:+city:mumbai +title:pizza。是的,我在索引和查询期间都使用了 StandardAnalyzer()。是的,我已经安装了 LukeAll。没有索引城市名称,即孟买不是小写的,但在查询中城市名称是小写的。可能这就是点击次数变为零的原因。但怎么可能呢?在这两种情况下,我都使用了相同的分析仪。
  • 其实一开始我已经将索引中的城市字段设置为 NOT_ANALYZED。所以在索引中它不是小写的,即使在纠正之后我忘记再次运行索引器。相反,我一次又一次地运行搜索器,所以在卢克中我看到城市字段没有小写。这就是不匹配的原因。对不起我的错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-29
  • 1970-01-01
相关资源
最近更新 更多