07_Lucene搜索

搜索

对要搜索的信息创建Query查询对象,Lucene会根据Query查询对象生成最终的查询语法,类似关系数据库Sql语法一样Lucene也有自己的查询语法,比如:“name:lucene”表示查询Field的name为“lucene”的文档信息。
可通过两种方法创建查询对象:

  • 使用Lucene提供Query子类
    Query是一个抽象类,lucene提供了很多查询对象,比如TermQuery项精确查询,NumericRangeQuery数字范围查询等。
    如下代码:
    Query query = new TermQuery(new Term("name", "lucene"));

  • 使用QueryParse解析查询表达式
    QueryParse会将用户输入的查询表达式解析成Query对象实例。
    如下代码:
    QueryParser queryParser = new QueryParser("name", new IKAnalyzer());
    Query query = queryParser.parse("name:lucene");

各种查询

TermQuery:

根据词进行搜索(只能从文本中进行搜索)
TermQuery,通过项查询,TermQuery不使用分析器所以建议匹配不分词的Field域查询,比如订单号、分类ID号等。指定要查询的域和要查询的关键词。

    @Test
    public void testIndexTermQuery() throws Exception{
        //创建分词器(创建索引和搜索时所用的分词器必须一致)
        Analyzer analyzer = new IKAnalyzer();

        //指定索引和文档的目录
        Directory dir  = FSDirectory.open(new File("D:\\BaiduNetdiskDownload\\lucene_day01\\tmp"));
        IndexReader indexReader = IndexReader.open(dir);

        IndexSearcher indexSearcher = new IndexSearcher(indexReader);
        //创建词元:就是词,
        Term t = new Term("fileName" , "apache");
        //使用TermQuery查询,根据term对象进行查询
        TermQuery query = new TermQuery(t);
        //搜索:第一个参数为查询语句对象, 第二个参数:指定显示多少条
        TopDocs topdocs = indexSearcher.search(query , 10);
        //一共搜索到多少条记录
        System.out.println("=====count=====" + topdocs.totalHits);
        //从搜索结果对象中获取结果集
        ScoreDoc[] scoreDocs = topdocs.scoreDocs;

        for(ScoreDoc scoreDoc : scoreDocs){
            //获取docID
            int docID = scoreDoc.doc;
            //通过文档ID从硬盘中读取出对应的文档
            Document document = indexReader.document(docID);
            //get域名可以取出值 打印
            System.out.println("fileName:" + document.get("fileName"));
            System.out.println("fileSize:" + document.get("fileSize"));
            System.out.println("============================================================");
        }
    }

QueryParser:

根据域名进行搜索,可以设置默认搜索域,推荐使用. (只能从文本中进行搜索)
通过QueryParser也可以创建Query,QueryParser提供一个Parse方法,此方法可以直接根据查询语法来查询。Query对象执行的查询语法可通过System.out.println(query);查询,需要使用到分析器。建议创建索引时使用的分析器和查询索引时使用的分析器要一致。
1 , 需要加入queryParser依赖的jar包。
\lib\lucene-queryparser-4.10.3.jar
2,实现

private String searchField = "fileName";
    private String searchWord = "1.create web page.txt";

    @Test
    public void testIndexSearch() throws Exception{
        //创建分词器(创建索引和搜索时所用的分词器必须一致)
        Analyzer analyzer = new IKAnalyzer();

        //指定索引和文档的目录
        Directory dir  = FSDirectory.open(new File("D:\\BaiduNetdiskDownload\\lucene_day01\\tmp"));
        //索引和文档的读取对象
        DirectoryReader indexReader = IndexReader.open(dir);
        //创建索引的搜索对象
        IndexSearcher indexSearcher = new IndexSearcher(indexReader);
        /**
         * 默认搜索域作用:如果搜索语法中指定域名从指定域中搜索,如果搜索时只写了查询关键字,则从默认搜索域中进行搜索
         * 第一个参数:默认搜索域,
         * 第二个参数:分词器
         */
        QueryParser queryParser = new QueryParser("fileContent" , analyzer);
//        Query query = queryParser.parse("apache");//从默认域搜索
        Query query = queryParser.parse(searchField+":"+searchWord);//从指定域搜索
        /**
         * 搜索:
         * 第一个参数为查询语句对象
         * 第二个参数:指定显示多少条
         */
        TopDocs topDocs = indexSearcher.search(query, 10);
        //一共搜索到多少条记录
        System.out.println("=====count======"+topDocs.totalHits);
        //从搜索结果对象中获取结果集
        ScoreDoc[] scoreDocs = topDocs.scoreDocs;

        for (ScoreDoc scoreDoc : scoreDocs){
            //获取docId
            int docId = scoreDoc.doc;
            //通过文档ID从硬盘中读取出对应的文档
            Document document = indexReader.document(docId);
            System.out.println("fileName="+document.get("fileName"));
            System.out.println("fileSize="+document.get("fileSize"));
            System.out.println("=====================================");
        }
    }

NumericRangeQuery:

从数值范围进行搜索

@Test
    public void testNumericRangeQuery() throws Exception{
        //创建分词器(创建索引和搜索时所用的分词器必须一致)
        Analyzer analyzer = new IKAnalyzer();

        //指定索引和文档的目录
        FSDirectory dir = FSDirectory.open(new File("D:\\BaiduNetdiskDownload\\lucene_day01\\tmp"));
        IndexReader indexReader = IndexReader.open(dir);
        //创建索引的搜索对象
        IndexSearcher indexSearcher = new IndexSearcher(indexReader);

        //根据数字范围查询
        //查询文件大小,大于100 小于1000的文章
        /**
         * 第一个参数:域名
         * 第二个参数:最小值,
         * 第三个参数:最大值,
         * 第四个参数:是否包含最小值,
         * 第五个参数:是否包含最大值
         */

        NumericRangeQuery<Long> query = NumericRangeQuery.newLongRange("fileSize", 100L, 1000L, true, true);
        //搜索:第一个参数为查询语句对象, 第二个参数:指定显示多少条
        TopDocs topdocs = indexSearcher.search(query, 10);

        //从搜索结果对象中获取结果集
        ScoreDoc[] scoreDocs = topdocs.scoreDocs;

        for(ScoreDoc scoreDoc : scoreDocs){
            //获取docID
            int docID = scoreDoc.doc;
            //通过文档ID从硬盘中读取出对应的文档
            Document document = indexReader.document(docID);
            //get域名可以取出值 打印
            System.out.println("fileName:" + document.get("fileName"));
            System.out.println("fileSize:" + document.get("fileSize"));
            System.out.println("============================================================");
        }
    }

BooleanQuery:

  • 组合查询,可以设置组合条件,not and or.从多个域中进行查询
  • must相当于and关键字,是并且的意思
  • should,相当于or关键字或者的意思
  • must_not相当于not关键字, 非的意思
  • 注意:单独使用must_not 或者 独自使用must_not没有任何意义
    @Test
    public void testBooleanQuery() throws Exception{
        //创建分词器(创建索引和搜索时所用的分词器必须一致)
        Analyzer analyzer = new IKAnalyzer();

        //指定索引和文档的目录
        FSDirectory dir = FSDirectory.open(new File("D:\\BaiduNetdiskDownload\\lucene_day01\\tmp"));
        IndexReader indexReader = IndexReader.open(dir);
        //创建索引的搜索对象
        IndexSearcher indexSearcher = new IndexSearcher(indexReader);

        //布尔查询,就是可以根据多个条件组合进行查询
        //文件名称包含apache的,并且文件大小大于等于100 小于等于1000字节的文章
        BooleanQuery query = new BooleanQuery();

        //创建词元:就是词,
        Term t = new Term("fileName" , "apache");
        //使用TermQuery查询,根据term对象进行查询
        TermQuery termQuery = new TermQuery(t);

        //根据数字范围查询
        //查询文件大小,大于100 小于1000的文章
        NumericRangeQuery<Long> numQuery = NumericRangeQuery.newLongRange("fileSize", 100L, 1000L, true, true);

        //Occur是逻辑条件
        //must相当于and关键字,是并且的意思
        //should,相当于or关键字或者的意思
        //must_not相当于not关键字, 非的意思
        //注意:单独使用must_not  或者 独自使用must_not没有任何意义
        query.add(termQuery , BooleanClause.Occur.MUST);
        query.add(numQuery , BooleanClause.Occur.MUST);

        TopDocs topdocs = indexSearcher.search(query, 10);

        //从搜索结果对象中获取结果集
        ScoreDoc[] scoreDocs = topdocs.scoreDocs;

        for(ScoreDoc scoreDoc : scoreDocs){
            //获取docID
            int docID = scoreDoc.doc;
            //通过文档ID从硬盘中读取出对应的文档
            Document document = indexReader.document(docID);
            //get域名可以取出值 打印
            System.out.println("fileName:" + document.get("fileName"));
            System.out.println("fileSize:" + document.get("fileSize"));
            System.out.println("============================================================");
        }

    }

MatchAllDocsQuery:

查询出所有文档

@Test
    public void testMathAllQuery() throws Exception{
        //创建分词器(创建索引和所有时所用的分词器必须一致)
        Analyzer analyzer = new IKAnalyzer();
        
        //查询所有文档
        MatchAllDocsQuery query = new MatchAllDocsQuery();
        
        //指定索引和文档的目录
        Directory dir = FSDirectory.open(new File("E:\\dic"));
        //索引和文档的读取对象
        IndexReader indexReader = IndexReader.open(dir);
        //创建索引的搜索对象
        IndexSearcher indexSearcher = new IndexSearcher(indexReader);
        //搜索:第一个参数为查询语句对象, 第二个参数:指定显示多少条
        TopDocs topdocs = indexSearcher.search(query, 5);
        //一共搜索到多少条记录
        System.out.println("=====count=====" + topdocs.totalHits);
        //从搜索结果对象中获取结果集
        ScoreDoc[] scoreDocs = topdocs.scoreDocs;
        
        for(ScoreDoc scoreDoc : scoreDocs){
            //获取docID
            int docID = scoreDoc.doc;
            //通过文档ID从硬盘中读取出对应的文档
            Document document = indexReader.document(docID);
            //get域名可以取出值 打印
            System.out.println("fileName:" + document.get("fileName"));
            System.out.println("fileSize:" + document.get("fileSize"));
            System.out.println("============================================================");
        }
    }

MultiFieldQueryParser:

可以从多个域中进行查询,只有这些域中有关键词的存在就查询出来.

@Test
    public void testMultiFieldQueryParser() throws Exception{
        //创建分词器(创建索引和搜索时所用的分词器必须一致)
        Analyzer analyzer = new IKAnalyzer();

        //指定索引和文档的目录
        FSDirectory dir = FSDirectory.open(new File("D:\\BaiduNetdiskDownload\\lucene_day01\\tmp"));
        IndexReader indexReader = IndexReader.open(dir);
        //创建索引的搜索对象
        IndexSearcher indexSearcher = new IndexSearcher(indexReader);

        String[] fields = {"fileName" , "fileContext"};
        //从文件名称和文件内容中查询,只有含有apache的就查出来
        MultiFieldQueryParser queryParser = new MultiFieldQueryParser(fields , analyzer);
        //输入需要搜索的关键字
        Query query = queryParser.parse("apache");
        //搜索:第一个参数为查询语句对象, 第二个参数:指定显示多少条
        TopDocs topdocs = indexSearcher.search(query, 10);

        //从搜索结果对象中获取结果集
        ScoreDoc[] scoreDocs = topdocs.scoreDocs;

        for(ScoreDoc scoreDoc : scoreDocs){
            //获取docID
            int docID = scoreDoc.doc;
            //通过文档ID从硬盘中读取出对应的文档
            Document document = indexReader.document(docID);
            //get域名可以取出值 打印
            System.out.println("fileName:" + document.get("fileName"));
            System.out.println("fileSize:" + document.get("fileSize"));
            System.out.println("============================================================");
        }
    }
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容