使lucene字符串字段范围可搜索

时间:2017-09-25 07:44:41

标签: java lucene

我是Lucene的新手,并且在使字符串字段在一个范围内可搜索时遇到了一些问题。

所以,我有一个由几个字符串字段组成的文档。其中一个是具有表格

的版本

1.0,1.1,1.0-RC1 ......即Major.Minor(-RCX)

版本字符串有一个支持java类(Version),它实现了Comparable。

我的分析器是一个分析器包装器,它是一个LowerCase和WhiteSpace分析器,类似于内置的分析器。我使用经典查询解析器进行搜索。搜索确切的术语可以正常工作。

我希望能够做到的是:

查询:“版本:[1.0-RC1至1.5]” - 列出两个值之间的所有文档匹配版本

psuedoquery:“someField:value AND version:latest” - 列出所有带有someField = value且具有最新版本的文档

我尝试做的是在索引之前将我的版本字符串转换为int,但是查询输入需要以某种方式进行转换,以便在搜索之前版本字符串变为和int。我还尝试使用具有三维的IntPoint但是来了无处可去。

看起来我必须为版本字段实现自定义分析器,但是我在查找类似示例时遇到了问题。

如果有人能指出我的方向会很棒!

谢谢!

1 个答案:

答案 0 :(得分:0)

你没有提到Lucene版本所以我假设最新版(> = 6.0.0)。

TermRangeQuery似乎适合您的需要,但我过去没有使用过这门课程。

我在下面写了示例程序进行测试,它似乎给了我想要的结果。使用以下代码时,请包括所需的lucene罐子。

package lucene.productversion;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.core.SimpleAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.document.StringField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.IndexWriterConfig.OpenMode;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TermRangeQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.FSDirectory;


public class App 
{
    private static String versionField = "version";

    public static void main( String[] args ) throws IOException
    {
        App app = new App();

        System.out.println( "Staring Product Version!" );

        File indexDir = new File("D:\\experiments");
        FSDirectory directory = FSDirectory.open(indexDir.toPath());

        Analyzer analyzer = new SimpleAnalyzer();

        app.index(analyzer, directory);

        app.search(analyzer, directory);

        System.out.println( "End Product Version!" );

    }

    private void search(Analyzer analyzer,FSDirectory directory) throws IOException{

        IndexReader reader = DirectoryReader.open(directory);
        IndexSearcher searcher = new IndexSearcher(reader);

        Query query =  TermRangeQuery.newStringRange(versionField, "1.0", "2.1-RC2", true, true);

        TopDocs topDocs  = searcher.search(query, 10);


        if(topDocs.totalHits <= 0 ){
            System.out.println("No Hits Found");
            return;
        }

        for(ScoreDoc doc:topDocs.scoreDocs){
            System.out.println("Doc Id :"+doc.doc+" Version Number :"+searcher.doc(doc.doc).get(versionField));
        }

        reader.close();

        System.out.println("Searching Completed");
    }

    private void index(Analyzer analyzer,FSDirectory directory) throws IOException{

        IndexWriterConfig config = new IndexWriterConfig(analyzer);

        config.setOpenMode(OpenMode.CREATE);

        IndexWriter writer = new IndexWriter(directory, config);


        for(String version:versions()){
            Document doc = new Document();

            doc.add(new StringField(versionField,version,Store.YES));

            writer.addDocument(doc);

        }

        writer.commit();
        writer.close();

        System.out.println("Indexing Completed");
    }

    private List<String> versions(){

        List<String> versions = new ArrayList<>();

        versions.add("1.0");
        versions.add("1.0-RC1");
        versions.add("1.1");
        versions.add("1.2");
        versions.add("2.1-RC1");
        versions.add("2.1-RC2");
        versions.add("2.1-RC3");
        versions.add("3.1-RC1");
        versions.add("3.1");

        return versions;
    }
}
相关问题