Lucene.Net 2.3.1开发介绍 —— 四、搜索(二)

简介: 原文:Lucene.Net 2.3.1开发介绍 —— 四、搜索(二) 4.3 表达式用户搜索,只会输入一个或几个词,也可能是一句话。输入的语句是如何变成搜索条件的上一篇已经略有提及。 4.3.1 观察表达式在研究表达式之前,一定要知道,任何一个Query都会对于一个表达式。
原文: Lucene.Net 2.3.1开发介绍 —— 四、搜索(二)

4.3 表达式
用户搜索,只会输入一个或几个词,也可能是一句话。输入的语句是如何变成搜索条件的上一篇已经略有提及。

4.3.1 观察表达式
在研究表达式之前,一定要知道,任何一个Query都会对于一个表达式。不光可以通过Query构造表达式,还可以通过拼接字符串构造。这里说的观察表达式是指,用Query完成查询语句后,用ToString()方法输出Query的表达式。很简单是吧,呵呵。

4.3.2 表达式的与或非
“与或非”让我想起上学的时候学的门电路 ==#。先动手看看什么是与或非。

 

代码 4.3.2.1
using System;
using System.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;

namespace Test
{
[TestFixture]
public class StandardAnalyzerCaseTest
{
/// <summary>
/// 执行测试的入口
/// </summary>
[Test]
public void SearcherTest()
{
Index();
List
<string> list = new List<string>() { "测试" };
for (int i = 0; i < list.Count; i++)
{
Console.WriteLine(
"搜索词:" + list[i]);
Console.WriteLine(
"结果:");
Searcher(list[i]);
Console.WriteLine(
"-----------------------------------");
}
}

/// <summary>
/// 搜索
/// </summary>
/// <param name="querystring">搜索输入</param>
private void Searcher(string querystring)
{
Analyzer analyzer
= new StandardAnalyzer();
IndexSearcher searcher
= new IndexSearcher("IndexDirectory");
QueryParser parser
= new QueryParser("content", analyzer);
Query query
= parser.Parse(querystring);
//输出我们要查看的表达式
Console.WriteLine(query.ToString());
Hits hits
= searcher.Search(query);
for (int i = 0; i < hits.Length(); i++)
{
Document doc
= hits.Doc(i);
Console.WriteLine(doc.Get(
"title"));
}
}

/// <summary>
/// 索引数据
/// </summary>
private void Index()
{
Analyzer analyzer
= new StandardAnalyzer();
IndexWriter writer
= new 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">tag的boost</param>
void AddDocument(IndexWriter writer, string title, string content)
{
Document document
= new Document();
document.Add(
new Field("title", title, Field.Store.YES, Field.Index.TOKENIZED));
document.Add(
new Field("content", content, Field.Store.YES, Field.Index.TOKENIZED));
writer.AddDocument(document);
}
}
}

 

先准备好代码4.3.2.1,OK,现在测试。结果输出:

搜索词:测试
结果:
content:"测 试"
测试系统
来测试
测试测
-----------------------------------

第三行,就是表达式。这个表达式不知道是什么意思?输入了“测试”这两个字进行搜索,怎么会变成 “content:"测 试"”呢?可以看出,“测试”中间空了一个空格,还多了一个content。“测试”中间有空格不难理解,是分词器对它进行拆分的结果。至于content,这个需要把目光转到QueryParser类上去,在构造QueryParser类的时候,就加了这么个参数。这个是表面要搜索哪个字段。为了验证这个想法,现在把“测试”换成英文“ab”,把content换成title.

也就是替换以下两句:

List<string> list = new List<string>() { "ab" };         //在方法SearcherTest中
QueryParser parser = new 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
<string> list = new List<string>() { "真是" };
for (int i = 0; i < list.Count; i++)
{
Console.WriteLine(
"搜索词:" + list[i]);
Console.WriteLine(
"结果:");
Searcher(list[i]);
Console.WriteLine(
"-----------------------------------");
}
}

/// <summary>
/// 搜索
/// </summary>
/// <param name="querystring">搜索输入</param>
private void Searcher(string querystring)
{
Analyzer analyzer
= new StandardAnalyzer();

//构造BooleanQuery
QueryParser parser = new QueryParser("content", analyzer);
BooleanQuery bquery
= new BooleanQuery();
TokenStream ts
= analyzer.TokenStream(null, new StringReader(querystring));
Lucene.Net.Analysis.Token token;
while ((token = ts.Next()) != null)
{
Query query
= parser.Parse(token.TermText());
bquery.Add(query, BooleanClause.Occur.MUST);
}
//构造完成

IndexSearcher searcher
= new IndexSearcher("IndexDirectory");

//Query query = parser.Parse(querystring);
//输出我们要查看的表达式
Console.WriteLine(bquery.ToString());
Hits hits
= searcher.Search(bquery);
for (int i = 0; i < hits.Length(); i++)
{
Document doc
= hits.Doc(i);
Console.WriteLine(doc.Get(
"title"));
}
}

 

测试:

搜索词:真是
结果:
+content:真 +content:是
测试测
-----------------------------------

构造出与的表达式了。把BooleanQuery的Add方法第二个参数换成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的运算符的话,那只有这么两个也太单调了。实际上它还有其它运算符。

+-!():^[]{}~*?

上面的字符都是它的运算符号,这么多运算符用起来很方便。但是也就出现另外一个问题。

 

什么问题?下一节再讲。

目录
相关文章
|
1月前
|
SQL 开发框架 数据可视化
企业应用开发中.NET EF常用哪种模式?
企业应用开发中.NET EF常用哪种模式?
|
2月前
|
开发框架 JavaScript 前端开发
5个.NET开源且强大的快速开发框架(帮助你提高生产效率)
5个.NET开源且强大的快速开发框架(帮助你提高生产效率)
|
9天前
|
开发框架 前端开发 JavaScript
采用C#.Net +JavaScript 开发的云LIS系统源码 二级医院应用案例有演示
技术架构:Asp.NET CORE 3.1 MVC + SQLserver + Redis等 开发语言:C# 6.0、JavaScript 前端框架:JQuery、EasyUI、Bootstrap 后端框架:MVC、SQLSugar等 数 据 库:SQLserver 2012
|
1月前
|
数据安全/隐私保护 Windows
.net三层架构开发步骤
.net三层架构开发步骤
11 0
|
1月前
深入.net平台的分层开发
深入.net平台的分层开发
54 0
|
2月前
|
开发框架 前端开发 .NET
福利来袭,.NET Core开发5大案例,30w字PDF文档大放送!!!
为了便于大家查找,特将之前开发的.Net Core相关的五大案例整理成文,共计440页,32w字,免费提供给大家,文章底部有PDF下载链接。
33 1
福利来袭,.NET Core开发5大案例,30w字PDF文档大放送!!!
|
3月前
|
C#
.NET开发中合理使用对象映射库,简化和提高工作效率
.NET开发中合理使用对象映射库,简化和提高工作效率
|
3月前
|
开发框架 前端开发 JavaScript
一款基于.NET Core的快速开发框架、支持多种前端UI、内置代码生成器
一款基于.NET Core的快速开发框架、支持多种前端UI、内置代码生成器
|
4月前
|
JavaScript C#
【傻瓜级JS-DLL-WINCC-PLC交互】2.wincc使用C#开发的.net控件
【傻瓜级JS-DLL-WINCC-PLC交互】2.wincc使用C#开发的.net控件
41 0
|
4月前
|
小程序 安全 JavaScript
.NET微信网页开发之通过UnionID机制解决多应用用户帐号统一问题
.NET微信网页开发之通过UnionID机制解决多应用用户帐号统一问题
.NET微信网页开发之通过UnionID机制解决多应用用户帐号统一问题