4.3 表达式
用户搜索
只会输入
个或几个词
也可能是
句话
输入
语句是如何变成搜索条件
上
篇已经略有提及
4.3.1 观察表达式
在研究表达式的前
定要知道
任何
个Query都会对于
个表达式
不光可以通过Query构造表达式
还可以通过拼接
串构造
这里说
观察表达式是指
用Query完成查询语句后
用
思路方法输出Query
表达式
很简单是吧
呵呵
4.3.2 表达式
和或非
“和或非”让我想起上学
时候学
门电路
#
先动手看看什么是和或非
代码 4.3.2.1
using ;
using .Collections.Generic;
using Lucene.Net.Analysis;
using Lucene.Net.Analysis.Standard;
using Lucene.Net.Documents;
using Lucene.Net.Index;
using Lucene.Net.QueryParsers;
using Lucene.Net.Search;
using NUnit.Framework;
Test
{
[TestFixture]
public StandardAnalyzerCaseTest
{
/// <summary>
/// 执行测试入口
/// </summary>
[Test]
public void SearcherTest
{
Index;
List<> list = List<> { "测试" };
for ( i = 0; i < list.Count; i)
{
Console.WriteLine("搜索词:" + list[i]);
Console.WriteLine("结果:");
Searcher(list[i]);
Console.WriteLine("-----------------------------------");
}
}
/// <summary>
/// 搜索
/// </summary>
/// <param name="query">搜索输入</param>
private void Searcher( query)
{
Analyzer analyzer = StandardAnalyzer;
IndexSearcher searcher = IndexSearcher("IndexDirectory");
QueryParser parser = QueryParser("content", analyzer);
Query query = parser.Parse(query);
//输出我们要查看表达式
Console.WriteLine(query.);
Hits hits = searcher.Search(query);
for ( i = 0; i < hits.Length; i)
{
Document doc = hits.Doc(i);
Console.WriteLine(doc.Get("title"));
}
}
/// <summary>
/// 索引数据
/// </summary>
private void Index
{
Analyzer analyzer = StandardAnalyzer;
IndexWriter writer = IndexWriter("IndexDirectory", analyzer, true);
AddDocument(writer, "测试", @"测定是123123ab阿布");
AddDocument(writer, "测试测", @"测试搜索真是不是 ");
AddDocument(writer, "来测试", @"好好测试山");
AddDocument(writer, "测试系统", @"测试样例");
writer.Optimize;
writer.Close;
}
/// <summary>
/// 添加文档
/// </summary>
/// <param name="writer">维护文档管理器</param>
/// <param name="title">标题</param>
/// <param name="content">内容</param>
/// <param name="tag">tag</param>
/// <param name="boost">tagboost</param>
void AddDocument(IndexWriter writer, title, content)
{
Document document = Document;
document.Add( Field("title", title, Field.Store.YES, Field.Index.TOKENIZED));
document.Add( Field("content", content, Field.Store.YES, Field.Index.TOKENIZED));
writer.AddDocument(document);
}
}
}
先准备好代码4.3.2.1
OK
现在测试
结果输出:
搜索词:测试
结果:
content:"测 试"
测试系统
来测试
测试测
-----------------------------------
第 3行
就是表达式
这个表达式不知道是什么意思?输入了“测试”这两个字进行搜索
如何会变成 “content:"测 试"”呢?可以看出
“测试”中间空了
个空格
还多了
个content
“测试”中间有空格不难理解
是分词器对它进行拆分
结果
至于content,这个需要把目光转到QueryParser类上去
在构造QueryParser类
时候
就加了这么个参数
这个是表面要搜索哪个字段
为了验证这个想法
现在把“测试”换成英文“ab”
把content换成title.
也就是替换以下两句:
List<> list = List<> { "ab" }; //在思路方法SearcherTest中
QueryParser parser = QueryParser("title", analyzer); //在思路方法Searcher中
现在再测试
下:
搜索词:ab
结果:
title:ab
-----------------------------------
看到了
果然是这样
现在把查询
字段还是换成content,然后把关键字换成“真是”
搜索词:真是
结果:
content:"真 是"
-----------------------------------
结果出来了
也印证了上面
想法
但是明明有
条记录同时包含这两个字了
为什么没有搜索到呢?是不是加个空格就可以了呢?把“真
”变成“真
”
再来试试
搜索词:真 是
结果:
content:真 content:是
测试测
测试
-----------------------------------
真神奇
表达式变掉了
而且只包含
个“是”但是没有“真”
记录也出来了
这表明什么?这表明现在
语句就是或
关系
只要满足包含“是”或者包含“真”就可以搜索到了
(以上内容前面章节有提到
现在开始进入正式气氛
——Birdshover)
但是我现在就想要搜索同时包含两个字
记录如何办呢?嘿嘿
在每个字前面加个“+”号试试
关键词变成“+真 +是”看看结果:
搜索词:+真 +是
结果:
+content:真 +content:是
测试测
-----------------------------------
那现在我要搜索包含“是”但是不包含“真”
结果
如何办?试试这个语句“-真 +是”
搜索词:-真 +是
结果:
-content:真 +content:是
测试
-----------------------------------
和或非终于被我们折腾完了
整理总结下关系就是:
a & b => +a +b
a || b => a b
a !b => +a -b
4.3.3 如何用Query构造和或非
Lucene.Net框架提供
Query也是可以完成和或非运算
般用BooleanQuery来构造
如何构造?现在对搜索部分代码进行变动
变成4.3.3.1
代码 4.3.3.1
/// <summary>
/// 执行测试入口
/// </summary>
[Test]
public void SearcherTest
{
Index;
List<> list = List<> { "真是" };
for ( i = 0; i < list.Count; i)
{
Console.WriteLine("搜索词:" + list[i]);
Console.WriteLine("结果:");
Searcher(list[i]);
Console.WriteLine("-----------------------------------");
}
}
/// <summary>
/// 搜索
/// </summary>
/// <param name="query">搜索输入</param>
private void Searcher( query)
{
Analyzer analyzer = StandardAnalyzer;
//构造BooleanQuery
QueryParser parser = QueryParser("content", analyzer);
BooleanQuery bquery = BooleanQuery;
TokenStream ts = analyzer.TokenStream(null, StringReader(query));
Lucene.Net.Analysis.Token token;
while ((token = ts.Next) != null)
{
Query query = parser.Parse(token.TermText);
bquery.Add(query, BooleanClause.Occur.MUST);
}
//构造完成
IndexSearcher searcher = IndexSearcher("IndexDirectory");
//Query query = parser.Parse(query);
//输出我们要查看表达式
Console.WriteLine(bquery.);
Hits hits = searcher.Search(bquery);
for ( i = 0; i < hits.Length; i)
{
Document doc = hits.Doc(i);
Console.WriteLine(doc.Get("title"));
}
}
测试:
搜索词:真是
结果:
+content:真 +content:是
测试测
-----------------------------------
构造出和
表达式了
把BooleanQuery
Add思路方法第 2个参数换成BooleanClause.Occur.SHOULD
bquery.Add(query, BooleanClause.Occur.SHOULD);
这个就是或:
搜索词:真是
结果:
content:真 content:是
测试测
测试
-----------------------------------
而换成 bquery.Add(query, BooleanClause.Occur.MUST_NOT);这个就是非了:
搜索词:真是
结果:
-content:真 -content:是
-----------------------------------
4.3.4 其它特使符号
如果形容"+-"为Lucene.Net
运算符
话
那只有这么两个也太单调了
实际上它还有其它运算符
+-!
:^
{}~*?
上面
都是它
运算符号
这么多运算符用起来很方便
但是也就出现另外
个问题
什么问题?下
节再讲