【问题标题】:lucene query fuzzy in one field and exact in anotherlucene 查询在一个字段中模糊而在另一个字段中准确
【发布时间】:2014-03-02 17:58:43
【问题描述】:

问题:

如何在 lucene 4.5 中将一个字段中的完全匹配和另一个字段中的模糊搜索结合起来?

问题:

我已在 lucene 索引中索引了 NGA Geonames 地名词典。我需要模糊查询一个字段(地名),但将查询限制为具有特定国家代码的记录。这是我正在运行的示例查询
我没有使用 SOLR,我已经做了很多研究和反复试验,但我没有明确的答案,可能是我速度慢。

FULL_NAME_ND_RO:india AND CC1:in 

我想要在印度进行模糊搜索,但我只想要与“in”(国家代码)完全匹配的记录

Here is what I've tried:
1. Index every field as a textfield and boost the country code field using ^N. Still returns different country codes, and the one boosted does not always come first...
2. Index every field as text EXCEPT the country code, which I indexed as StringField. This way I get no results at all.

这里是 Gaz 的索引代码:

public void index(File outputIndexDir, File gazateerInputData, GazType type) throws Exception {
    if (!outputIndexDir.isDirectory()) {
      throw new IllegalArgumentException("outputIndexDir must be a directory.");
    }

    String indexloc = outputIndexDir + type.toString();
    Directory index = new MMapDirectory(new File(indexloc));

    Analyzer a = new StandardAnalyzer(Version.LUCENE_45);
    IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_45, a);

    IndexWriter w = new IndexWriter(index, config);

    readFile(gazateerInputData, w, type);
    w.commit();
    w.close();

  }

  public void readFile(File gazateerInputData, IndexWriter w, GazType type) throws Exception {
    BufferedReader reader = new BufferedReader(new FileReader(gazateerInputData));
    List<String> fields = new ArrayList<String>();
    int counter = 0;
    // int langCodeIndex = 0;
    System.out.println("reading gazateer data from file...........");
    while (reader.read() != -1) {
      String line = reader.readLine();
      String[] values = line.split(type.getSeparator());
      if (counter == 0) {
        for (String columnName : values) {
          fields.add(columnName.replace("»¿", "").trim());
        }

      } else {
        Document doc = new Document();
        for (int i = 0; i < fields.size() - 1; i++) {
          if (fields.get(i).equals("CC1")) {
            doc.add(new StringField(fields.get(i), values[i], Field.Store.YES));
          } else {
            doc.add(new TextField(fields.get(i), values[i], Field.Store.YES));
          }
        }

        w.addDocument(doc);

      }
      counter++;
      if (counter % 10000 == 0) {
        w.commit();
        System.out.println(counter + " .........committed to index..............");
      }

    }
    w.commit();
    System.out.println("Completed indexing gaz! index name is: " + type.toString());
  }

这是运行查询的代码

QueryParser parser = new QueryParser(Version.LUCENE_45, luceneQueryString, geonamesAnalyzer);
  Query q = parser.parse(luceneQueryString);

  TopDocs search = geonamesSearcher.search(q, rowsReturned);

geonamesAnalyzer 是一个 StandardAnalyzer....luceneQueryString 就像上面的查询。

任何建议都会很棒。

【问题讨论】:

    标签: lucene


    【解决方案1】:

    最简单的答案似乎是使用the appropriate query syntax 运行模糊查询,例如:

     FULL_NAME_ND_RO:india~ AND CC1:in
    

    但是,如果您需要以不同的方式分析每个字段,您可以使用 PerFieldAnalyzerWrapper


    基于以下cmets:

    StandardAnalyzer 中设置的默认停用词包括单词“in”,因此搜索词完全从查询中删除。可以通过appropriate StandardAnalyzer constructor 覆盖停用词集:

    StandardAnalyzer(Version.LUCENE_45, new CharArraySet(Version.LUCENE_45, 0, true));
    

    由于 CC1 字段是一个 StringField(因此,在索引时不进行分析),因此确保在查询时也不对其进行分析可能是有意义的。虽然上述解决了停用词问题,但您可能还会遇到与案例相关或标记化问题,例如。 KeywordAnalyzer 通常适用于未分析的字段。可以将PerFieldAnalyzerWrapper 传递给查询解析器,以将不同的分析规则应用于不同的字段。

    类似:

    Map<String,Analyzer> analyzerPerField = new HashMap<String,Analyzer>();
    analyzerPerField.put("CC1", new KeywordAnalyzer());
    
    PerFieldAnalyzerWrapper aWrapper =
      new PerFieldAnalyzerWrapper(geonamesAnalyzer, analyzerPerField);
    
    QueryParser parser = new QueryParser(Version.LUCENE_45, defaultField, aWrapper);
    

    【讨论】:

    • 是的...我知道....问题是最好的模糊结果通常是在错误的国家。因此,对传入的国家代码的模糊命中可能是第 N 个命中“向下”。目前我只是检索大量结果,然后丢弃那些没有正确代码的结果。希望有更好的方法
    • 不确定我是否理解。使用AND operator,我看不到任何的结果如何可能有错误的国家代码。
    • 我同意,但显然小国家代码字符串只是与其他字段中的搜索一起加权...我通过一些缓存“解决”了这个问题,并且只返回了一吨结果并过滤掉不匹配的国家/地区代码。
    • 不,查询解析器不会仅仅因为它很短而决定忽略必填字段。我的猜测是您正在使用带有默认停用词集的StandardAnalyzer,其中包含“in”一词,因此该搜索词完全从查询中删除。您的国家/地区代码字段可能根本不应该被分析。 PerFieldAnalyzerWrapper 可用于轻松将不同的分析器应用于不同的领域。
    • 谢谢,我正在使用标准分析仪。我会调查这个
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多