自己动手写分布式搜索引擎
上QQ阅读APP看书,第一时间看更新

3.3.5 布尔查询

可以使用BooleanQuery组合多个查询条件。合取查询使用BooleanClause.Occur.MUST连接多个查询词。

        Term t1 = new Term(FIELD, "lucene");
        TermQuery q1 = new TermQuery(t1);


        Term t2 = new Term(FIELD, "doug");
        TermQuery q2 = new TermQuery(t2);


        //合取查询
        BooleanQuery query = new BooleanQuery();
        query.add(q1, BooleanClause.Occur.MUST); //必须包含这个条件
        query.add(q2, BooleanClause.Occur.MUST);

选择出包含任何一个查询词的文档叫作析取(Disjunction)。用真值表描述析取如下。

析取查询使用BooleanClause.Occur.SHOULD连接多个查询词。

        //析取查询
        BooleanQuery q = new BooleanQuery();
        q.Add(q1, BooleanClause.Occur.SHOULD); //可以只包含这个条件
        q.Add(q2, BooleanClause.Occur.SHOULD);

例如去餐馆点菜,有人不喜欢吃辣的东西,所以他找出所有不辣的菜,这叫作否定(Negation)。用真值表描述否定如下。

BooleanClause.Occur.MUST_NOT表示不能包括符合这个条件的文档。例如找出不包含“辣”的所有文档。

        Term t1 = new Term("body", "辣");
        TermQuery q1 = new TermQuery(t1);


        BooleanQuery mbq = new BooleanQuery();
        MatchAllDocsQuery alldocs = new MatchAllDocsQuery();  //匹配所有文档
        mbq.Add(q1, BooleanClause.Occur.MUST_NOT);  //不包括满足q1条件的文档
        mbq.Add(alldocs, BooleanClause.Occur.MUST);

打麻将三缺一不行,但是如果同时查询多个词,最好只差一个查询词的文档也能匹配。

对于长句搜索,则提取其中的主要查询词,只要大部分词在文档中出现就可以了。例如搜索联系方式列:

● "Stanford University School of Medicine, Palo Alto, CA USA",

● "Institute of Neurobiology, School of Medicine, Stanford University, Palo Alto, CA",

● "School of Medicine, Harvard University, Boston MA",

● "Brigham & Women's, Harvard University School of Medicine, Boston, MA"

● "Harvard University, Cambridge MA"

搜索联系方式使用如下的长查询词:

        "School of Medicine, Stanford University, Palo Alto, CA"

需要找到所有和Stanford相关的文档。

PhraseQuery要求短语中所有的词都存在才能匹配。这里需要一个更加宽松的PhraseQuery版本,要求它对词出现的顺序敏感,但是允许缺少个别词,缺少词的文档分值低,但是仍然能匹配。BooleanQuery.setMinimumNumberShouldMatch(int)方法可以定义需要匹配的条件的最小数量。

例如,BooleanQuery中有2项,调用BooleanQuery.setMinimumNumberShouldMatch(1)方法可以匹配其中任意的1项或者更多。

        Term t1 = new Term(FIELD, "鸡");
        TermQuery q1 = new TermQuery(t1);


        Term t2 = new Term(FIELD, "鸭");
        TermQuery q2 = new TermQuery(t2);


        BooleanQuery mbq = new BooleanQuery();
        mbq.add(q1 , BooleanClause.Occur.SHOULD);
        mbq.add(q2 , BooleanClause.Occur.SHOULD);
        mbq.setMinimumNumberShouldMatch(1);