简介
参考文章:https://www.cnblogs.com/eggTwo/p/4425269.html
现在主流网站,APP都有“站内搜索”的功能:优酷,爱奇艺,链家,携程......等等。如果用SQL做站内搜索的话,
例如:select * from t where Title like '%西游记%' 这种方式的缺点就是:容易全表扫描,性能不好,对数据库的压力大
现在我们一种搜索引擎服务器可以解决我们的问题
全文检索引擎开发包有 Lucene ,Solr ,Elastic Search等
其中Lucene是Java编写的全文检索引擎引擎底层开发包,它也有.Net移植版本,叫Lucene.Net 。基于Lucene开发难度比较大。因此有人开发出了基于Lucene的搜索引擎服务器,Solr ,Elastic Search等
环境搭建
现在我们要讲的就是Elasticc Search搜索引擎服务器
Elasticc Search搜索引擎服务器简称ES ,它是使用Java开发的,因此运行的时候要配置Java的运行环境。这些搜索引擎服务器都是“客户端SDK+服务器”的这种使用方法
第一步:Elasticc Search安装
1> 下载安装Java运行环境JDK1.8
2> Java的环境变量配置
win7系统: 首先右击【计算机】进入【属性】然后选择其中的【高级系统设置】点击进入【高级】中的【环境变量】,进入环境变量编辑界面。
点击新建
变量名(N)叫 JAVA_HOME
变量值 就是你Java JDB1.8的安装目录
点击确定,那么Java的环境变量配置就配置好了
第二步:下载安装Elasticc Search
去官网地址下载 Elasticc Search:https://www.elastic.co/cn/downloads/elasticsearch
我下载的是最近版本:6.2.3 下载后,解压,我解压到了D盘 (注意如果是6.2.3版本测试发现数据保存失败,我后来更换成了5.2.0版本,根据保存成功)
打开cmd ,cd到 D:\elasticsearch-6.2.3文件夹下的bin目录,然后执行 elasticcsearch.bat
回车执行
【如果执行过程中报 Error occurred during initialization of VM
Could not reserve enough space for object heap 错误 】那么我们只要去D:\elasticsearch-6.2.3文件夹下的config文件夹下找到jvm.options 文件,将服务占用的堆栈空间改小点就行了:改法如下图
执行完毕后我们可以在本机浏览器中输入127.0.0.1:9200来检查 elasticsearch服务是否运行成功
【注意:执行完毕后这个cmd窗口不要关闭,关闭后服务就停止了】
看到以下情况则表示成功。(如果用IE浏览器打开的话可能弹出一个让你保存的Json文件,如果Json文件内容是如下的话也表示服务运行成功)
第三步:使用
以上服务器都搭建好了,下面就来演示怎么通过代码来连接这个 Elasticc Search服务器
SDK有很多中驱动,如: ElasticSearch.Net ,NEST , PlainElastic.Net 等都可以使用,这里就使用PlainElastic.Net
1> 在项目中 通过Nuget安装PlainElastic.Net
控制器中调用:
存数据
using PlainElastic.Net;
using PlainElastic.Net.Serialization;
using System;
using System.Web.Mvc;
namespace ElasticSearch.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
Person p1 = new Person();
p1.Id = 100698;
p1.Age = 18;
p1.Name = "林黛玉ere";
p1.Describe = "ee林黛玉与贾宝玉青春年少,有共同的理想志趣和叛逆精神而慢慢发展成爱情。绛珠还泪的神话赋予了林黛玉迷人的诗人气质,为宝黛爱情注入了带有奇幻元素的罗曼蒂克色彩,同时又定下了悲剧基调。";
try
{
ElasticConnection client = new ElasticConnection("127.0.0.1", 9200);
var serializer = new JsonNetSerializer();
//第一个参数相当于“数据库”,第二个参数相当于“表”,第三个参数相当于“主键”
IndexCommand cmd = new IndexCommand("yzk", "persons", p1.Id.ToString());
//Put()第二个参数是要插入的数据
OperationResult result = client.Put(cmd, serializer.Serialize(p1));
var indexResult = serializer.ToIndexResult(result.Result);
if (indexResult.created)
{
return Content("创建成功");
}
else
{
return Content("没创建" + indexResult.error);
}
}
catch (Exception ex)
{
string msg = ex.Message;
throw ex;
}
//如何知道插入成功?看 indexResult 返回值。如果 id 已经存在,则不再插入,如果想覆盖 update 的话,就要先删再插。
}
}
public class Person
{
public int Id { get; set; }
public int Age { get; set; }
public string Name { get; set; }
public string Describe { get; set; }
}
}
读取数据
/// <summary>
/// 读取数据(查询DbIndexName数据库中TbIndexType表的Field字段中包含Context值的数据)
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="DbIndexName">存的时候设置的值(相当于数据库)</param>
/// <param name="TbIndexType">存的时候设置的值(相当于表)</param>
/// <param name="Field">表的字段</param>
/// <param name="Context">字段的内容</param>
/// <returns></returns>
public SearchResult<T> Search<T>(string DbIndexName, string TbIndexType, string Field, string Context)
{
ElasticConnection client = new ElasticConnection("127.0.0.1", 9200);
SearchCommand cmd = new SearchCommand(DbIndexName, TbIndexType);
var query = new QueryBuilder<T>();
query = query.Query(r => r.Bool(
m => m.Must(t => t.QueryString(t1 => t1.DefaultField(Field).Query(Context)))
));
string querySql = query.Build();
var result = client.Post(cmd, querySql);
var serializer = new JsonNetSerializer();
SearchResult<T> list = serializer.ToSearchResult<T>(result);
return list;
}
在控制器中对获取到的数据遍历
public class HomeController : Controller
{
public ActionResult Index()
{
//注意:这个数据使用的是延迟加载
var resultData = Search<Person>("yzk", "persons", "Describe", "贾宝玉的");
var count = resultData.hits.total;//获取到查询到数据的总条数
var took = resultData.took; //查询数据花费的毫秒数
//第一种
var list = resultData.hits.hits.Select(r => new Person()
{
Id = r._source.Id,
Name = r._source.Name,
Age = r._source.Age,
Describe = r._source.Describe
}).ToList();
//第二种
foreach (var item in resultData.Documents)
{
var id = item.Id;
var name = item.Name;
var age = item.Age;
var Describe = item.Describe;
}
return View(list);
}
}
删除
(ES没有更新,如果想更新一条数据,就先删除,然后再插入)
/// <summary>
/// 删除
/// </summary>
/// <param name="DbIndexName">存的时候设置的值(相当于数据库)</param>
/// <param name="TbIndexType">存的时候设置的值(相当于表)</param>
/// <param name="Id">存的时候设置的值(主键)</param>
/// <returns></returns>
public OperationResult Delete(string DbIndexName, string TbIndexType, string Id)
{
ElasticConnection client = new ElasticConnection("127.0.0.1", 9200);
DeleteCommand cmd = new DeleteCommand(DbIndexName, TbIndexType, Id);
var result = client.Delete(cmd);
return result;
}