zoukankan      html  css  js  c++  java
  • Lucene.Net 学习(搜索部分)(低要求,写给自己看)

    1. 搜索

       排序:lucene 提供了Sort类对结果进行排序

       提供了Filter类对查询条件进行限制

       你或许会不自觉地拿它跟SQL语句进行比较:“lucene能执行and、or、order by、where、like ‘%xx%’操作吗?”回答是:“当然没问题!”

      7.1 各种各样的Query

        下面我们看看lucene到底允许我们进行哪些查询操作:

        7.1.1 TermQuery

           首先介绍最基本的查询,如果你想执行一个这样的查询: “在content域中包含‘lucene’的document.rdquo;,那么你可以用TermQuery:
              Term t = new Term("content", " lucene");
              Query query = new TermQuery(t);

        7.1.2 BooleanQuery

           如果你想这么查询:“在content域中 包含java或perl的document.rdquo;,那么你可以建立两个TermQuery并把它们用BooleanQuery连接起来:
              TermQuery termQuery1 = new TermQuery(new Term("content", "java");
              TermQuery termQuery2 = new TermQuery(new Term("content", "perl");
              BooleanQuery booleanQuery = new BooleanQuery();
              booleanQuery.add(termQuery1, BooleanClause.Occur.SHOULD);
              booleanQuery.add(termQuery2, BooleanClause.Occur.SHOULD);

        7.1.3 WildcardQuery

           如果你想对某单词进行通配符查询,你可以用WildcardQuery,通配符包括’?’匹配一个任意字符和’*’匹配零个或多个任意字符,例如你搜索’use*’,你可能找到’useful’或者’useless’:
              Query query = new WildcardQuery(new Term("content", "use*"));

        7.1.4 PhraseQuery(这个或许可以不考虑)

           你可能对中日关系比较感兴趣,想查找‘中’和‘日’挨得比较近(5个字的距离内)的文章,超过这个距离的不予考虑,你可以:

              PhraseQuery query = new PhraseQuery();
              query.setSlop(5);
              query.add(new Term("content ", “中”));
              query.add(new Term(“content”, “日”));

           那么它可能搜到“中日合作……”、“中方和日方……”,但是搜不到“中国某高层领导说日本欠扁”。

        7.1.5 PrefixQuery

           如果你想搜以‘中’开头的词语,你可以用PrefixQuery:

              PrefixQuery query = new PrefixQuery(new Term("content ", "中");

        7.1.6 FuzzyQuery(或许可以不考虑使用)

           FuzzyQuery用来搜索相似的term,使用Levenshtein算法。假设你想搜索跟‘wuzza’相似的词语,你可以:

              Query query = new FuzzyQuery(new Term("content", "wuzza"));

           你可能得到‘fuzzy’和‘wuzzy’。

        7.1.7 RangeQuery

           另一个常用的Query是RangeQuery,你也许想搜索时间域从20060101到20060130之间的document.你可以用RangeQuery:

              RangeQuery query = new RangeQuery(new Term(“time”, “20060101”), new Term(“time”, “20060130”), true);

           改了:

                //TermRangeQuery rq = new TermRangeQuery("SalaryMin", salaryMin.ToString(), salaryMax.ToString(), true, true);
                bq.Add(NumericRangeQuery.NewIntRange("SalaryMin", salaryMin, salaryMax, true, false),Occur.MUST);
                bq.Add(NumericRangeQuery.NewIntRange("SalaryMax", salaryMin, salaryMax, true, true), Occur.MUST);

           最后的true表示用闭合区间。

      7.2 QueryParser

          看了这么多Query,你可能会问:“不会让我自己组合各种Query吧,太麻烦了!”

          当然不会,lucene提供了一种类似于SQL语句的查询语句,我们姑且叫它lucene语句,通过它,你可以把各种查询一句话搞定,lucene会自动把它们查分成小块交给相应Query执行。

        下面我们对应每种 Query演示一下:

            TermQuery可以用“field:key”方式,例如“content:lucene”

            BooleanQuery‘与’用‘+’‘或’用‘ ’,例如“content:java contenterl”

            WildcardQuery仍然用‘?’和‘*’,例如“content:use*”

            PhraseQuery‘~’,例如“content:"中日"~5”

            (以。。。开头)PrefixQuery‘*’,例如“中*”

            (相似的词)FuzzyQuery‘~’,例如“content: wuzza ~”

            RangeQuery‘[]’或‘{}’前者表示闭区间,后者表示开区间,例如“time:[20060101 TO 20060130]”注意TO区分大小写

          你可以任意组合query string,完成复杂操作,例如“标题或正文包括lucene,并且时间在20060101到20060130之间的文章” 可以表示为:“+ (title:lucene content:lucene) +time:[20060101 TO 20060130]”

        代码如下:

            Directory dir = FSDirectory.getDirectory(PATH, false);
            IndexSearcher ins = new IndexSearcher(dir);
            QueryParser parser = new QueryParser("content", new StandardAnalyzer());                 
            Query query = parser.Parse("+(title:lucene content:lucene) +time:[20060101 TO 20060130]");
            Hits hits = ins.search(query);                                                           
            for (int i = 0; i < hits.length(); i++)
            {
              document.doc = hits.doc(i);
              System.out.println(doc.get("title");
            }
            ins.close();

          首先我们创建一个在指定文件目录上的IndexSearcher。
          然后创建一个使用StandardAnalyzer作为分析器的QueryParser,它默认搜索的域是content。
          接着我们用QueryParser来parse查询字串,生成一个Query。
          然后利用这个Query去查找结果,结果以Hits的形式返回。
          这个Hits对象包含一个列表,我们挨个把它的内容显示出来。

        7.3 Filter       

           filter的作用就是限制只查询索引的某个子集,它的作用有点像SQL语句里的 where,但又有区别,它不是正规查询的一部分,只是对数据源进行预处理,然后交给查询语句。

           注意它执行的是预处理,而不是对查询结果进行过滤,所以使用filter的代价是很大的,它可能会使一次查询耗时提高一百倍。

           最常用的filter是RangeFilter和QueryFilter。RangeFilter是设定只搜索指定范围内的索引;QueryFilter是在上次查询的结果中搜索。Filter的使用非常简单,你只需创建一个filter实例,然后把它传给searcher。

      其他形式的搜索:

                //----------------这里配置搜索条件----------------
                PhraseQuery query = new PhraseQuery();
                foreach (string word in Common.SplitContent.SplitWords(searchKey))        //将用户输入的关键字进行分词
                {
                    query.Add(new Term("content", word));
                    //query.Add(new Term("content", "C#"));     //多个查询条件时 为且的关系
                }
    
                //关键词Or关系设置
                BooleanQuery queryOr = new BooleanQuery();
                TermQuery query = null;
                foreach (string word in Common.SplitContent.SplitWords(searchKey))
                {
                    query = new TermQuery(new Term("content", word));
                    queryOr.Add(query, Occur.SHOULD);               //这里设置条件为Or关系
                }
    
                query.Boost = 100;      //query.SetSlop(100); //指定关键词相隔最大距离
    
                //盛放查询结果的容器
                TopScoreDocCollector collector = TopScoreDocCollector.Create(1000, true);
                //searcher.Search(query, null, collector);          //根据query查询条件进行查询,查询结果放入collector容器
                searcher.Search(queryOr, null, collector);          //根据queryOr查询条件进行查询,查询结果放入collector容器
  • 相关阅读:
    MVC视图布局页常用代码
    常用meta标签及说明
    重新认识Android
    为什么V8引擎这么快?
    node.js入门及express.js框架
    红星美凯龙CEO车建新的圆融和霸气
    【一个王朝的背影】--余秋雨
    Android源代码结构分析
    Android文件系统的结构
    Mac OSX 平台安装 MongoDB
  • 原文地址:https://www.cnblogs.com/zhangchaoran/p/8310937.html
Copyright © 2011-2022 走看看