ES 使用小结

Posted 皖苏

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ES 使用小结相关的知识,希望对你有一定的参考价值。

 ES 是 Elastic Search 的缩写,可以理解为一个支持分布式部署的软件。

部署了以后可以当数据库用,虽然官方不建议这样做,但我们是这样干的。 

它解决了很多场景下的查询需求,发版速度飞快,用的人蛮多的,使用 Java 开发并开源。

我刚接触没几天遇到了很多坑,在这里记录一下。

  1、如何精确查询中文字段?

使用 keyword 特性,让分析器不进行拆词,然后使用 term query。如:

1 [Keyword(Name = nameof(CompanyName), Index = true)]
2 public string CompanyName { get; set; }
        /// <summary>
        /// Term Query 根据公司名称查询
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public IEnumerable<EnterpriseCreditInfo> SearchByName(string name)
        {
            var searchedList = this.client
                .Search<EnterpriseCreditInfo>(
                    m => m.Index(index).Query(q =>
                    //q.MatchPhrase(mc => mc.Field(ff => ff.CompanyName).Query(name))
                    q.Term(t => t.Field(f => f.CompanyName).Value(name))
                    ));
            return searchedList.Hits.Select(m =>
            {
                m.Source.Id = m.Id;
                return m.Source;
            });
        }

    2、为什么使用 text 特性 标记后使用 term query 查询中文查不到数据?如:

[Text(Name = nameof(CompanyName), Index = true)]
public string CompanyName { get; set; }

 Text 特性和 Keyword 特性都是表示 string 类型的。

  其中 Keyword 特性表示将索引 field 的值。

  Text 表示使用分析器进行拆词索引多个 term 。

所以 Text 可以指定分词器而 Keyword 则不行。 如指定 ik 中文分词器:

 [Text(Name = nameof(CompanyName), Index = true, Analyzer = "ik")]
  public string CompanyName { get; set; }

至于为什么无法命中索引,是因为默认的 Analyzer = "standard" 分词器会将中文分成一个汉字一个 term 所以直接查询 term 是查询不到的。

  3、如何分词查询中文(全文搜索)?可以使用 match 系列 。自己百度去。

  4、使用 Nest 创建索引的方法有哪些?

        /// <summary>
        /// 默认的初始化 client
        /// </summary>
        /// <param name="nodes">服务器集群</param>
        /// <param name="index">索引名</param>
        protected virtual void InitClient(IEnumerable<Uri> nodes, string index)
        {
            var pool = new StaticConnectionPool(nodes);

            var settings = new ConnectionSettings(pool);
            settings.DefaultIndex(index);
            settings.DisableDirectStreaming(true);//影响性能发布时注释,用于抓取 request 和 response。 
            client = new ElasticClient(settings.ThrowExceptions()); //直接抛出异常,发布时去掉。
            var exits = client.IndexExists(index);

            if (!exits.Exists)
            {
                CreateIndex(index + "_real", index);//默认使用别名,方便索引重建。
            }
        }
        /// <summary>
        /// 当索引不存在的时候创建索引。
        /// 根据 <see cref="Nest.ElasticsearchTypeAttribute"/> 自动映射类型
        /// 默认创建 NumberOfShards = 5
        /// 默认创建 NumberOfReplicas = 1,
        /// </summary>
        /// <param name="index"></param>
        protected virtual void CreateIndex(string index, string Alias)
        {
            var descriptor = new CreateIndexDescriptor(index)
                .Settings(s =>
                s.NumberOfShards(5).NumberOfReplicas(1))
                .Aliases(m => m.Alias(Alias))
                .Mappings(ms => ms.Map<T>(m => m
                .Properties(ps => ps
                   .Text(t => t.Name(n => n.Id))
                   .Text(t => t.Name(n => n.CreateTime).Index(true)))
                .AutoMap()));

            client.CreateIndex(descriptor);

        }

5、如何使用类似于 sql-in 的查询操作?

  使用操作符| 、& 等拼接 term query ,可以实现各种查询,如 term any (网上抄的):

        /// <summary>
        /// term any item of <paramref name="values"/>
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="descriptor"></param>
        /// <param name="field"></param>
        /// <param name="values"></param>
        /// <returns></returns>
        protected static QueryContainer TermAny(QueryContainerDescriptor<T> descriptor, Field field, IEnumerable<string> values)
        {
            QueryContainer q = new QueryContainer();
            foreach (var value in values)
            {
                q |= descriptor.Term(t => t.Field(field).Value(value));
            }
            return q;
        }

6、其他注意事项:

1、小写,index 和 type 要小写,否则抛异常。

 term 是小写的。所以比如 term query   

descriptor.Term(t => t.Field(field).Value("Foo")); 辣鸡 查不出来。用 keyword 不知道区不区分,一会试试再补。

 帮到你的话点赞。

 

 

以上是关于ES 使用小结的主要内容,如果未能解决你的问题,请参考以下文章

ES6 学习小结1

ES 使用小结

ES6新特性使用小结

ES6新特性使用小结

ES6新特性使用小结

ES:学习小结2