Elasticsearch架设起来之后,以服务器的方式运行。Elasticsearch对外提供RESTFUL Api接口,通过以下方式访问:
1.GUI方面:有像kopf之类的Plugin可以用。
2.自己写程序操作接RESTFUL Api
3.通过浏览器访问
4.客户端Elasticsearch .NET:像是连Stack Overflow都使用的NEST。
NEST is a high level .NET client for Elasticsearch which provides a way to call Elasticsearch REST APIs via strongly-typed, easy to use, query DSL.
Elasticsearch.Net. NEST uses the Elasticsearch.Net low level client to dispatch requests and responses, using and extending many of the types within Elasticsearch.Net.
elastic团队开发了2个Elasticsearch .NET的套件,一个是Elasticsearch.Net,一个是NEST,而两者的差异只在于NEST是Elasticsearch.Net的Wrapper,NEST还是base on Elasticsearch.Net,只是NEST提供比较友善的使用方式,让我们在Coding的时候踩的雷比较少,如果我们需要比较进阶的操作是NEST没有提供的,我们还是可以使用Elasticsearch.Net。
Elasticsearch和关系型数据库sql server术语对照表
关系数据库 ⇒ 数据库 ⇒ 表 ⇒ 行 ⇒ 列(Columns)
Elasticsearch ⇒ 索引(Index) ⇒ 类型(type) ⇒ 文档(Docments) ⇒ 字段(Fields)
建立联机建立联机有2种方式:
1.联机到单一服务器。
namespace Nop.Web.Components
{
//----new 20210511
[ViewComponent(Name = "BlogMoreLikeThis")]
public class BlogMoreLikeThisViewComponent : ViewComponent
{
#region Fields
readonly IConfiguration _configuration;
#endregion
public BlogMoreLikeThisViewComponent(IConfiguration configuration)
{
_configuration = configuration;
}
public async Task<IViewComponentResult> InvokeAsync(string query)
{
SearchViewModel viewModel = new SearchViewModel();
//如果查询字符串为空,则直接返回
if (String.IsNullOrEmpty(query))
{
return View(viewModel);
}
try
{
// 1.设置
var nodeUrl = _configuration["BlogMoreLikeThis:ConnectionString"];
var indexName = _configuration["BlogMoreLikeThis:IndexName"];
// var node = new Uri("http://localhost:9200"); //old
var node = new Uri(nodeUrl); //new
var settings = new ConnectionSettings(node);
// settings.DefaultIndex("wwwiaspnetcoreindex"); //old
settings.DefaultIndex(indexName); //new
var client = new ElasticClient(settings);
//获取分页参数
int currentPageIndex = 0;
int itemsPerPage = 10;
string queryString = query;
var preQueryString = client.Indices.Analyze(a => a.Index(indexName).Analyzer("ik_max_word").Text(queryString));
if (!preQueryString.IsValid)
throw new ArgumentNullException("字符串分词失败");
var queryStringLagerThanTwoHzHashSet = new HashSet<string>();
string queryStringLagerThanTwoHz = "";
foreach (var item in preQueryString.Tokens)
{
int len = item.Token.Length;
if ((len >= 2) && !queryStringLagerThanTwoHz.Contains(item.Token)) //大于两个汉字且字符串中没有同样的
{
queryStringLagerThanTwoHz += item.Token + " ";
}
}
var searchResults421 = client.Search<BlogPostModel>(s => s
.Index(indexName)
.Query(q => q.QueryString(qs => qs.Query(queryString).DefaultOperator(Operator.Or)))
);
var searchResults420 = client.Search<BlogPostModel>(s => s //高亮成功,加标题,成功
.From(currentPageIndex)
.Size(itemsPerPage)
.Query(q => q.QueryString(qs => qs.Query(queryString).DefaultOperator(Operator.Or)))
.Sort(ss => ss.Descending(p => p.CreatedOn))// 加入时间排序
.Highlight(h => h
.PreTags("<b>")
.PostTags("</b>")
.Fields(f => f.Field(e => e.Body).PreTags("<font color =\"red\">").PostTags("</font>"),
f => f.Field(e => e.Title).PreTags("<font color =\"red\">").PostTags("</font>")))
);
//返回结构用户显示
var returnsearchResults = new Tuple<IEnumerable<IHit<BlogPostModel>>, long>(searchResults421.Hits, searchResults421.Took);
viewModel.Results = searchResults421.Hits;
viewModel.Elapsed = searchResults421.Took;
viewModel.Total = searchResults421.Total;
viewModel.Query = query;
viewModel.Paging.CurrentPage = currentPageIndex + 1;
viewModel.Paging.ItemsPerPage = itemsPerPage;
viewModel.Paging.TotalItems = (int)searchResults421.Total;
return View(viewModel);
}
catch (Exception ex)
{
return View(viewModel);
}
}
}
2.建立服务器群,让NEST自己选择联机到运作正常的服务器。
private ElasticClient ConnectToConnectionPool()
{
//建立服务器群
var elasticNodes = new SniffingConnectionPool(new Uri[] { new Uri(@“http://elasticsearch01:9200”),new Uri(@“http://elasticsearch02:9200”),new Uri(@“http://elasticsearch03:9200”)});
//产生联机设定,指定服务器群及预设的index名称。
var connectionSetting = new ConnectionSettings(elasticNodes,“myindex0”);
//建立Elasticsearch Client,请重覆使用。
return new ElasticClient(connectionSetting);
}
索引单笔document要索引一笔document其实很容易。
private void IndexDocument()
{
//假设有一个
TextItem的objectTextItem textItem = new TextItem()
{Id = Guid.NewGuid(),Summary =“I'm summary.”,Content =“I'm content.”,AuthorId =“99999”,AuthorName =“Dotblogs”,CreatedTime = DateTime.Now,ModifiedTime = DateTime.Now};
//直接呼叫Index将object给入即可。
//官网建议自行指定document Id,不指定的话预设Elasticsearch会自己给。
// type如果不指定,预设就是类别名称。
this.myindexClient.Index(textItem,indexDescriptor => indexDescriptor.Id(textItem.Id.ToString()));}
IndexDescriptor是用来改变我们在索引数据时的参数,我们可藉由Index方法的重载给入Func<IndexDescriptor<T>,IndexDescriptor<T>>,像上述的例子我们自行将object的Id指定为document的Id,其他像index、type都可以自行指定。索引多笔document要索引多笔document我们要用另一个方法Bulk。
private void IndexMultipleDocuments()
{
//假设我产生了多个TextItemList<TextItem> textItems = CreateTextItems();
//呼叫Bulk方法,给入一个BulkRequest object,指定BulkRequest.Operations为List<IBulkOperation<TextItem>>。
//this.myindexClient.Bulk(new BulkRequest(){Operations = textItems.Select(t => new BulkIndexOperation<TextItem>(t){ Id = t.Id.ToString()} as IBulkOperation).ToList()});
}
//要索引多笔数据我们可以跑循环一笔一笔用Index方法处理当然也是没问题的,不过这对于Elasticsearch来讲是不一样的,跑回圈用Index方法是「你一笔一笔来我一笔一笔做」,而用Bulk方法一次丢则是「你全部一起来我全部一起做」,在效率上用Bulk一次索引多笔数据绝对是占上风的。.