第四节:基于Elastic.Clients.Elasticsearch进行索引库和文档的操作

一.  初始化配置

1  事先准备

(1) 类库: Elastic.Clients.Elasticsearch 8.18.3

(2) 初始化注册client

builder.Services.AddSingleton<ElasticsearchClient>(sp =>
{
    var configuration = sp.GetRequiredService<IConfiguration>();
    var settings = new ElasticsearchClientSettings(new Uri("http://11.11.11.80:9200"))
        //.Authentication(new BasicAuthentication("elastic", "your_password"))     //账号密码
        //.DefaultIndex("t_book")                                                  //默认索引库名称, 推荐crud的时候显示传入
        .ServerCertificateValidationCallback((sender, cert, chain, errors) => true); // 开发环境忽略证书

    return new ElasticsearchClient(settings);
});
builder.Services.AddScoped<BookService>();

(3) 实体准备  (后面章节全部使用这个实体)

public class Book
{
    public string id { get; set; }
    public string title { get; set; }
    public string category { get; set; }
    public string author { get; set; }
    public decimal price { get; set; }
    public DateTime published_date { get; set; }
    public List<string> tags { get; set; } = new();
    //高亮显示(不需要在ES创建字段)
    public string highlightTitle { get; set; }
}

 

 

二. 索引库操作

1. 初始化索引

2 删除索引

public class BookService
{
    private readonly ElasticsearchClient _client;
    private readonly string indexName = "t_book";  //索引库名称,必须显式声明,只能小写

    public BookService(ElasticsearchClient client)
    {
        _client = client;
    }

    /*****************************************下面是索引库相关操作******************************************/

    #region 01-创建索引(带分词器配置)
    /// <summary>
    /// 01-创建索引(带分词器配置)
    /// </summary>
    /// <returns></returns>
    /// <exception cref="Exception"></exception>
    public async Task CreateIndexAsync()
    {
        var exists = await _client.Indices.ExistsAsync(indexName);
        if (exists.Exists) return;

        var response = await _client.Indices.CreateAsync(indexName, c => c
            .Settings(s => s.NumberOfShards(1).NumberOfReplicas(0))
            .Mappings(m => m
                .Properties<Book>(p => p
                    .Keyword(k => k.id)
                    .Text(t => t.title, f => f.Analyzer("ik_max_word"))     // 中文分词(需安装IK插件)
                    .Text(t => t.author, f => f.Analyzer("ik_smart"))       // 中文分词(需安装IK插件)
                    .Keyword(t=>t.category)
                    .FloatNumber(n => n.price)
                    .Date(d => d.published_date)
                    .Keyword(k => k.tags)      // 标签不分词,用于精确查询
                )
            )
        );
        if (!response.IsValidResponse)
            throw new Exception($"创建索引失败: {response.DebugInformation}");
    }
    #endregion

    #region 02-删除索引
    /// <summary>
    /// 02-删除索引
    /// </summary>
    /// <returns></returns>
    public async Task DeleteIndexAsync()
    {
        await _client.Indices.DeleteAsync(indexName);
    }
    #endregion
    }     

 

 

三. 文档基本CRUD

1 文档的CRUD

BookService代码

public class BookService
{
    private readonly ElasticsearchClient _client;
    private readonly string indexName = "t_book";  //索引库名称,必须显式声明,只能小写

    public BookService(ElasticsearchClient client)
    {
        _client = client;
    }

    /*****************************************下面是文档基本相关操作******************************************/

    #region 01-单个新增文档
    /// <summary>
    /// 01-单个新增文档
    /// </summary>
    /// <param name="book"></param>
    /// <returns></returns>
    /// <exception cref="Exception"></exception>
    public async Task<string> AddBookAsync(Book book)
    {
        //https://www.elastic.co/docs/reference/elasticsearch/clients/dotnet/getting-started#_getting_documents
        var response = await _client.IndexAsync(book, x => x.Index(indexName));  //官方写法

        //var response = await _client.IndexAsync(book);   //这种写法必须初始化连接的时候打开.DefaultIndex("t_book"),显然不灵活
        if (!response.IsValidResponse)
            throw new Exception($"添加文档失败: {response.DebugInformation}");

        return response.Id;
    }
    #endregion

    #region 02-批量新增文档
    /// <summary>
    /// 02-批量新增文档
    /// </summary>
    /// <param name="books"></param>
    /// <returns></returns>
    /// <exception cref="Exception"></exception>
    public async Task BulkAddBooksAsync(IEnumerable<Book> books)
    {
        var response = await _client.IndexManyAsync(books, indexName);

        if (!response.IsValidResponse)
        {
            var errors = response.Items
                .Where(item => !item.IsValid)
                .Select(item => $"文档 {item.Id}: {item.Error?.Reason}")
                .ToList();

            throw new Exception($"批量添加失败: {string.Join("\n", errors)}");
        }
    }
    #endregion

    #region  03-删除文档
    /// <summary>
    /// 03-删除文档
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public async Task<bool> DeleteBookAsync(string id)
    {
        var response = await _client.DeleteAsync<Book>(indexName, id);
        return response.IsSuccess();
    }
    #endregion

    #region 04-更新文档
    /// <summary>
    /// 04-更新文档
    /// </summary>
    /// <param name="book"></param>
    /// <returns></returns>
    /// <exception cref="Exception"></exception>
    public async Task UpdateBookAsync(Book book)
    {
        var response = await _client.UpdateAsync<Book, Book>(indexName, book.id, u => u.Doc(book));
        if (!response.IsValidResponse)
            throw new Exception($"更新失败: {response.DebugInformation}");
    }
    #endregion

    #region 05-根据ID查询文档
    /// <summary>
    /// 05-根据ID查询文档
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public async Task<Book> GetBookByIdAsync(string id)
    {
        var response = await _client.GetAsync<Book>(id, idx => idx.Index(indexName));
        if (!response.IsValidResponse || !response.Found)
            return null;
        return response.Source;
    }
    #endregion

}

控制器中代码

查看代码
     #region 01-添加书籍
    /// <summary>
    /// 01-添加书籍
    /// </summary>
    /// <returns></returns>
    [HttpPost]
    public async Task<IActionResult> AddBook()
    {
        //var bookList = new List<Book>
        //{
        //    new() {
        //        Id = "1",
        //        Title = "深入理解Elasticsearch:分布式搜索与数据分析",
        //        Author = "张三",
        //        Price = 69.99m,
        //        PublishedDate = DateTime.Now.AddMonths(-3),
        //        Tags = ["技术", "数据库", "搜索"]
        //    },
        //    new() {
        //        Id = "2",
        //        Title = ".NET Core微服务架构与实践",
        //        Author = "李四",
        //        Price = 79.50m,
        //        PublishedDate = DateTime.Now.AddMonths(-1),
        //        Tags = ["编程", "微服务", "架构"]
        //    },
        //    new() {
        //        Id = "3",
        //        Title = "搜索引擎优化实战",
        //        Author = "王五",
        //        Price = 55.00m,
        //        PublishedDate = DateTime.Now.AddDays(-15),
        //        Tags = ["SEO", "网络营销"]
        //    }
        //};
        //逐个添加
        //List<string> idList = [];
        //foreach (var book in bookList)
        //{
        //    var id = await _bookService.AddBookAsync(book);
        //    idList.Add(id);
        //}

        var bookList = GenerateTestBooks(100);   //模拟100条数据插入

        //批量添加
        await _bookService.BulkAddBooksAsync(bookList);


        return Json(new { status = "ok", msg = "添加成功" });
    }
    #endregion

    #region 02-删除书籍
    /// <summary>
    /// 02-删除书籍
    /// </summary>
    /// <param name="id">编号Id</param>
    /// <returns></returns>
    [HttpPost]
    public async Task<IActionResult> DeleteBook(string id)
    {
        var success = await _bookService.DeleteBookAsync(id);
        if (success)
        {
            return Json(new { status = "ok", msg = "删除成功" });
        }
        return Json(new { status = "error", msg = "删除失败" });
    }
    #endregion

    #region 03-获取书籍
    /// <summary>
    ///  03-获取书籍
    /// </summary>
    /// <param name="id">编号</param>
    /// <returns></returns>
    [HttpPost]
    public async Task<ActionResult<Book>> GetBook(string id)
    {
        var book = await _bookService.GetBookByIdAsync(id);
        return Json(new { status = "ok", msg = "获取成功", data = book });
    }
    #endregion

    #region 04-更新书籍
    /// <summary>
    /// 04-更新书籍
    /// </summary>
    /// <returns></returns>
    [HttpPost]
    public async Task<IActionResult> UpdateBook()
    {

        Book newBook = new()
        {
            id = "1",
            title = "深入理解Elasticsearch:分布式搜索与数据分析",
            author = "ypf",
            price = 69.99m,
            published_date = DateTime.Now.AddMonths(-3),
            tags = ["技术", "数据库", "搜索"]
        };
        await _bookService.UpdateBookAsync(newBook);

        return Json(new { status = "ok", msg = "获取成功", });
    }
    #endregion

    #region 手动生成数据
    [NonAction]
    public List<Book> GenerateTestBooks(int count = 100)
    {
        var books = new List<Book>();
        var random = new Random();
        var currentId = 1;

        // 书籍类别
        var categories = new[]
        {
        "计算机科学", "人工智能", "数据科学", "软件开发", "网络技术",
        "云计算", "前端开发", "后端开发", "移动开发", "数据库",
        "系统架构", "信息安全", "编程语言", "算法", "设计模式",
        "项目管理", "用户体验", "游戏开发", "嵌入式系统", "量子计算"
    };

        // 书籍标题组件
        var titlePrefixes = new[] { "深入理解", "精通", "实战", "高级", "现代", "分布式", "云原生", "高效" };
        var titleTechs = new[] { "Elasticsearch", "微服务", "Kubernetes", "Docker", "React", "Vue", "Angular", "机器学习", "人工智能", "大数据" };
        var titleSuffixes = new[] { "原理与实践", "开发指南", "权威指南", "核心原理", "实战手册", "最佳实践", "系统设计", "应用开发" };

        // 作者相关
        var firstNames = new[] { "张", "王", "李", "赵", "刘", "陈", "杨", "黄", "周", "吴" };
        var lastNames = new[] { "伟", "芳", "娜", "敏", "静", "丽", "强", "磊", "军", "洋", "勇", "艳", "杰", "涛" };

        // 标签库
        var allTags = new[]
        {
        "技术", "编程", "数据库", "前端", "后端", "云计算", "架构",
        "微服务", "容器化", "DevOps", "大数据", "AI", "机器学习",
        "网络安全", "移动开发", "Web开发", "算法", "设计模式",
        "性能优化", "测试驱动", "敏捷开发", "领域驱动", "开源",
        "Java", "C#", "Python", "JavaScript", "Go", "Rust"
    };

        // 生成书籍
        for (int i = 0; i < count; i++)
        {
            // 生成随机类别
            var category = categories[random.Next(categories.Length)];

            // 生成随机标题(基于类别)
            var title = $"{titlePrefixes[random.Next(titlePrefixes.Length)]}{category}中的{titleTechs[random.Next(titleTechs.Length)]}{titleSuffixes[random.Next(titleSuffixes.Length)]}";

            // 30%的几率添加副标题
            if (random.NextDouble() < 0.3)
            {
                title += $": {titlePrefixes[random.Next(titlePrefixes.Length)]}{titleTechs[random.Next(titleTechs.Length)]}应用";
            }

            // 生成作者
            var author = $"{firstNames[random.Next(firstNames.Length)]}{lastNames[random.Next(lastNames.Length)]}";

            // 20%的几率添加第二作者
            if (random.NextDouble() < 0.2)
            {
                author += $", {firstNames[random.Next(firstNames.Length)]}{lastNames[random.Next(lastNames.Length)]}";
            }

            // 生成价格(基于类别)
            var basePrice = category switch
            {
                "人工智能" or "量子计算" => 80,
                "数据科学" or "云计算" => 70,
                _ => 50
            };

            var price = Math.Round(basePrice + (random.NextDouble() * 40), 2);

            // 10%的几率是高价书
            if (random.NextDouble() < 0.1)
            {
                price = Math.Round(price * 1.5, 2);
            }

            // 生成出版日期(过去5年内)
            var publishedDate = DateTime.Now.AddYears(-5).AddDays(random.Next(5 * 365));

            // 生成标签(基于类别)
            var tags = new List<string> { category };

            // 添加技术标签
            tags.AddRange(allTags
                .OrderBy(x => random.Next())
                .Take(random.Next(2, 5)));

            // 确保标签不重复
            tags = tags.Distinct().ToList();

            // 添加书籍
            books.Add(new Book
            {
                id = currentId++.ToString(),
                title = title,
                category = category,
                author = author,
                price = (decimal)price,
                published_date = publishedDate,
                tags = tags
            });
        }

        // 添加一些特定书籍(用于测试分类和搜索)
        books.AddRange(new[]
        {
        new Book
        {
            id = "search-1",
            title = "Elasticsearch 权威指南:分布式搜索与大数据分析实战",
            category = "数据科学",
            author = "张明",
            price = 89.99m,
            published_date = DateTime.Now.AddMonths(-6),
            tags = new List<string> { "Elasticsearch", "搜索", "大数据", "分布式系统" }
        },
        new Book
        {
            id = "search-2",
            title = "实战Elastic Stack:日志管理与数据分析",
            category = "数据科学",
            author = "李技术",
            price = 75.50m,
            published_date = DateTime.Now.AddMonths(-3),
            tags = new List<string> { "Elasticsearch", "Kibana", "日志分析", "监控" }
        },
        new Book
        {
            id = "search-3",
            title = "搜索引擎核心技术详解",
            category = "计算机科学",
            author = "王搜索",
            price = 68.00m,
            published_date = DateTime.Now.AddMonths(-9),
            tags = new List<string> { "搜索引擎", "算法", "信息检索", "自然语言处理" }
        },
        new Book
        {
            id = "search-4",
            title = ".NET Core中使用Elasticsearch进行高效搜索",
            category = "软件开发",
            author = "陈开发者",
            price = 62.99m,
            published_date = DateTime.Now.AddMonths(-2),
            tags = new List<string> { ".NET", "C#", "Elasticsearch", "集成" }
        },
        new Book
        {
            id = "search-5",
            title = "大数据搜索与日志分析:基于Elastic Stack",
            category = "数据科学",
            author = "赵数据",
            price = 82.00m,
            published_date = DateTime.Now.AddMonths(-12),
            tags = new List<string> { "大数据", "Elasticsearch", "Logstash", "数据分析" }
        },
        new Book
        {
            id = "category-1",
            title = "人工智能在医疗诊断中的应用",
            category = "人工智能",
            author = "吴智能",
            price = 95.00m,
            published_date = DateTime.Now.AddMonths(-4),
            tags = new List<string> { "AI", "医疗", "深度学习", "图像识别" }
        },
        new Book
        {
            id = "category-2",
            title = "量子计算基础与算法实现",
            category = "量子计算",
            author = "郑量子",
            price = 110.00m,
            published_date = DateTime.Now.AddMonths(-8),
            tags = new List<string> { "量子", "算法", "物理", "计算科学" }
        }
    });

        return books;
    }
    #endregion

 

 

 

 

 

 

 

 

 

 

 

 

!

  • 作       者 : Yaopengfei(姚鹏飞)
  • 博客地址 : http://www.cnblogs.com/yaopengfei/
  • 声     明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
  • 声     明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
 
posted @ 2025-07-14 16:28  Yaopengfei  阅读(242)  评论(1)    收藏  举报