posts - 78, comments - 34, trackbacks - 0, articles - 1
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

2010-01-05 传智播客—luncene/compass

Posted on 2010-01-06 16:51 長城 阅读(1489) 评论(0)  编辑  收藏

北京好奇怪,昼夜温差很大,有点像月球。早起时窗上的冰霜很厚实,但到了白天阳光很足,风力很小,气温很好。大连现在确在降温,零下十几度,比较罕见。可能是我离开她一会,她却变冷了。呵呵~~

 

今日上午把lucene的高级部分给结束了。下午搞了一下CompassCompass是对lucene的封闭。因为lucene使用起来有些麻烦。

 

一、lucene高级

1.分词器

一般的分词器流程:

clip_image001
 

 


1)         输入文本:输入查询的内容。

2)         关键词切分:使用分词器取出关键词。

3)         去除停用词:去除没有多大意义的词,比如a,an,the,的,呢,吧。

4)         形态还原:将词的某种形态还原为原形,比如英文复数形式恢复到单数形式。

5)         转为小写:将英文转为小写,不区分大小写。

 

Lucene中的分词器

1)         单字分词:对应的类ChineseAnalyzer,将输入的字符串中的每个字做为关键字。比如“中国人加油!”,会被切分为“中”、“国”、“人”、“加”、“油”。(标点符号属于停用词)

2)         二分法分词:对应的类CJKAnalyzer,将输入的字符串以二分法分词。比如“中国人加油!”,会被切分为“中国”、“国人”、“人加”、“加油”这四个关键字。(标点符号属于停用词)

3)         词库分词:对应的类MMAnalyzer最为常用的分词器。比如“中国人加油!”,会被切分为“中国人”、“加油”。(标点符号属于停用词)

示例:

package cn.itcast.cc.anayzler;

 

import java.io.IOException;

import java.io.StringReader;

import jeasy.analysis.MMAnalyzer;

import org.apache.lucene.analysis.Analyzer;

import org.apache.lucene.analysis.Token;

import org.apache.lucene.analysis.TokenStream;

import org.apache.lucene.analysis.cjk.CJKAnalyzer;

import org.apache.lucene.analysis.cn.ChineseAnalyzer;

import org.junit.Test;

 

public class AnalyzerTest {

 

    Analyzer anaylzer1 = new ChineseAnalyzer();// 单字分词

    Analyzer anaylzer2 = new CJKAnalyzer();// 二分分词法

    Analyzer anaylzer3 = new MMAnalyzer();// 词库分词

 

    @Test

    public void test() throws IOException {

        String str = "中国人加油!";

        printAnalyzer(anaylzer1, str);

        printAnalyzer(anaylzer2, str);

        printAnalyzer(anaylzer3, str);

    }

 

    private void printAnalyzer(Analyzer analyzer, String str)

            throws IOException {

        TokenStream tokenStream = analyzer.tokenStream("text", new StringReader(

                str));

        System.out.println("*****分词器->" + analyzer.getClass().getName() + ",将'"

                + str + "'切分为:");

        Token token = new Token();

        while ((token = tokenStream.next(token)) != null) {

            System.out.println(token);

        }

    }

}

 

2.高亮

Lucene的高亮器(Highlighter类)可以实现lucene的关键字高亮:

package cn.itcast.cc.highlighter;

 

import org.apache.lucene.analysis.Analyzer;

import org.apache.lucene.document.*;

import org.apache.lucene.document.Field.*;

import org.apache.lucene.index.IndexWriter;

import org.apache.lucene.index.IndexWriter.MaxFieldLength;

import org.apache.lucene.queryParser.*;

import org.apache.lucene.search.*;

import org.apache.lucene.search.highlight.*;

import org.apache.lucene.search.highlight.Scorer;

import org.junit.Test;

import jeasy.analysis.MMAnalyzer;

 

public class HighLighterTesst {

    private String path = "./index/";// lucene的索引数据被保存在这个目录中

    private Analyzer analyzer = new MMAnalyzer();// 词库分词器

 

    @Test

    public void test() {

        try {

            // 创建索引数据

            IndexWriter indexWriter = new IndexWriter(this.path, this.analyzer,

                    MaxFieldLength.LIMITED);

            Document doc = new Document();

            doc.add(new Field("content", "中国人民加油!", Store.YES, Index.ANALYZED));

            indexWriter.addDocument(doc);

            indexWriter.close();

            // 查询数据

            IndexSearcher indexSearcher = new IndexSearcher(this.path);

            QueryParser queryParser = new MultiFieldQueryParser(

                    new String[] { "content" }, this.analyzer);

            Query query = queryParser.parse("加油");

            TopDocs topDocs = indexSearcher.search(query, null, 10);

            // 创建高亮

            // SimpleHTMLFormatter的默认值为"<a></a>"

            Formatter formatter = new SimpleHTMLFormatter("<span>", "</span>");

            Scorer scorer = new QueryScorer(query);

            Highlighter highlighter = new Highlighter(formatter, scorer);

            // 打印结果

            for (ScoreDoc scoreDoc : topDocs.scoreDocs) {

                // 取出查询结果

                Document searchdoc = indexSearcher.doc(scoreDoc.doc);

                String searchstr = searchdoc.getField("content").stringValue();

                // 添加高亮

                String histr = highlighter.getBestFragment(this.analyzer,

                        "content", searchstr);

                System.out.println(histr);

            }

            indexSearcher.close();

        } catch (Exception e) {

            e.printStackTrace();

        }

    }

}

 

3.排序(默认相关度排序)

a)          实验相关度排序,得分是在搜索时算出来的。

b)         影响区域

i.           整个文档

ii.          某个字段

1.          建立索引时,影响它的排名,创建QueryParser时指定“MultiFieldQueryParser(String[] fields, Analyzer analyzer, Map boosts)”中第三个参数为“new HashMap<String, Float>().put(String fieldname, float fraction)”提升对应字段内容的排名。一般网站内部搜索会将标题部分的内容提升,以至于标题内容的排名大于帖子内容或回复的排名。

2.          搜索时,标题与内容的含量排名,TopDoc有一个score属性,它是根据文档中关键字的数量,记录文档的得分。

c)   按指定的字段进行排序,就是在搜索时,指定的字段。

d)   Sort排序器,由类Sort实现。

Sort sort = new Sort();

sort.setSort(SortField field);

indexSearcher.search(query, null, 100, sort);

 

4.过滤器

在查询时添加一个过滤器,过滤掉查询后不想要的内容,由Filter接口实现。

String lower = NumberTools.longToString(3);

String upper = NumberTools.longToString(6);

Filter filter = new RangeFilter("id", lower, upper, true, false);

indexSearcher.search(query, filter, 100);

lucene中使用数值、日期数据时,必须使用NumberToolsDateTools。前后必须统一,比如使用longToStringLong转换为String,那么也必须使用stringToLongString转换为Long

 

5.搜索,Query的子类对应各种查询:

1)         TermQuery,关键词查询:

Term term = new Term("context", "加油");

Query query = new TermQuery(term);

indexSearcher.search(query, null, 100);

2)         RangeQuery,范围查询:

Term lower = new Term("content", NumberTools.longToString(3));

Term upper = new Term("content", NumberTools.longToString(10));

Query query = new RangeQuery(lower, upper, false/*包含边界*/);

indexSearcher.search(query, null, 100);

3)         WildcardQuery,通配符查询:

Term term = new Term("context", "?");//?匹配任意一个字符,*代表任意多个字符。

Query query = new TermQuery(term);

indexSearcher.search(query, null, 100);

indexSearcher.search(query, null, 100);

4)         PhraseQuery,短语查询:

PhraseQuery phraseQuery = new PhraseQuery();

phraseQuery.add(new Term("context", "中国人民"));

phraseQuery.add(new Term("context", "加油"));

phraseQuery.setSlop(5); // 指定关键词之间间隔的字符的最大数量

indexSearcher.search(query, null, 100);

5)         BooleanQuery,布尔查询:

Query query1 = new TermQuery(new Term("context", "中国人民"));

Query query2 = new TermQuery(new Term("context", "加油"));

BooleanQuery boolQuery = new BooleanQuery();

boolQuery.add(query1, Occur.MUST);

boolQuery.add(query2, Occur.SHOULD);//Occur的常量值:MUSTSHOULDMUST_NOT

indexSearcher.search(query, null, 100);

注意:经过分词器的所有字母,无论是添加索引还是查询,都会被转换为小写的。但上边这些查询类没有经过分词器,如果查询关键里有大写字母,将查询不到匹配的结果。所以在使用上边这些查询类时,查询文本中的字母全部为小写。我们之前使用的查询是通过QueryParser切分出查询关键字,所以使用QueryParser可以不注意大小写问题。

二、Compass

Compasslucene的框架,它与hibernate极其相似(但不具有hibernate那些高级功能,比如缓存技术)。汤兄弟做的好,因为学习lucene之前的课程正是hibernate,他将hibernatecompass对比了一下,使我们学习compass更加容易了。OK,我总结一下。

1.hibernatecompass

clip_image001[3]

 

clip_image001[5]

 


hibernate

compass

配置方式

1.编程方式:

  Configuation cfg = new Configu...();

  cfg.set...();

  ...

2.配置文件:

  //默认配置,文件名为“hibernate.cfg.xml

  Configuation cfg= new Configu...();

//指定文件名(文件名可变更)

//cfg.configure("hibernate.cfg.xml");

1.编程方式:

  CompassConfiguation cfg = new CompassConf...();

  cfg.set("key","value");

  ...

2.配置文件

  //默认配置,文件名为“compass.cfg.xml

  cfg.configure();

  //指定文件名(文件名可变更)

  cfg.configure("hibernate.cfg.xml");

配置文件

XML文件

注解

XML文件

注解

 

2.compass中的注解配置

package cn.itcast.cc.compass;

 

import org.compass.annotations.Index;

import org.compass.annotations.Searchable;

import org.compass.annotations.SearchableId;

import org.compass.annotations.SearchableProperty;

import org.compass.annotations.Store;

 

@Searchable

public class Article {

    private Long id;

    private String title;

    private String content;

    @SearchableId

    public Long getId() { return id;}

    @SearchableProperty(store = Store.YES, index = Index.ANALYZED, boost = 2.0F, excludeFromAll = ExcludeFromAll.YES/*这个属性的内容被查询忽略*/)

    public String getTitle() {return title;}

    @SearchableProperty(store = Store.YES, index = Index.ANALYZED)

    public String getContent() {return content;}

    public void setId(Long id) {this.id = id;}

    public void setTitle(String title) {this.title = title;}

    public void setContent(String content) {this.content = content;}

}

XML配置文件,可以查看“compass-2.2.0-M2/docs/reference/html_single/index.html”手册,内容较多。

3.compassAPI

CompassConfiguration cfg = new CompassConfiguration();

cfg.setConnection("./indexPath/");// 连接信息

cfg.addClass(Article.class);// 声明映射信息

Compass compassSessionFactory = cfg.buildCompass();

CompassTransaction tx = session.beginTransaction();

session.create(article);

tx.commit();

session.close();

其他API

session.find(String arg0);

session.save(Object arg0);

session.delete(Class arg0, Object arg1);

 

 

这两天的课程相对比较容易些,虽然容易但仍然需要一定的练习。后天就要学习jbpmOA项目了,终于开始第一个像样的项目了,呵呵!不过感觉并没想像中的那么复杂,因为有了jbpm


只有注册用户登录后才能发表评论。


网站导航: