• 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 不知道区不区分,一会试试再补。

     帮到你的话点赞。

    
    
  • 相关阅读:
    AcWing 900. 整数划分
    AcWing 913. 排队打水
    AcWing 897. 最长公共子序列
    AcWing 895. 最长上升子序列
    AcWing 902. 最短编辑距离
    AcWing 338. 计数问题
    AcWing 896. 最长上升子序列 II
    AcWing 779. 最长公共字符串后缀
    AcWing 282. 石子合并
    ASP.NET里常用的JS (转贴)
  • 原文地址:https://www.cnblogs.com/zhuwansu/p/9023337.html
Copyright © 2020-2023  润新知