You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Elasticsearch NEST C#客户端批量条件更新嵌套时间序列列表

基于NEST批量部分更新Elasticsearch嵌套列表的实现方法

问题背景

需要使用Elasticsearch .NET高级客户端NEST,批量对指定ID的文档进行嵌套列表的部分更新:仅修改history列表中匹配特定日期的quantity值,未匹配的日期数据保持不变;如果指定日期在原列表中不存在,则新增该条记录。已知全文档批量索引和全嵌套列表替换的实现方式,但不清楚嵌套列表的部分更新方法。

原文档示例

[
  {
    "id": 1,
    "description": "market 1",
    "salesprice": 10.9,
    "cost": 7.95957,
    "history": [
      {
        "historydate": "2020-01-01",
        "quantity": 1
      },
      {
        "historydate": "2020-02-01",
        "quantity": 2
      },
      {
        "historydate": "2020-04-01",
        "quantity": 5
      }
    ]
  },
  {
    "id": 2,
    "description": "market 2",
    "salesprice": 12,
    "cost": 12,
    "history": [
      {
        "historydate": "2020-01-01",
        "quantity": 1
      },
      {
        "historydate": "2020-02-01",
        "quantity": 2
      },
      {
        "historydate": "2020-03-01",
        "quantity": 6
      }
    ]
  }
]

更新需求

  • ID为1的文档:更新2020-02-01的quantity为9,新增2020-03-01的记录(quantity=11)
  • ID为2的文档:更新2020-02-01的quantity为20,更新2020-03-01的quantity为15

实现方案

核心思路是利用Elasticsearch的**脚本更新(Script Update)**结合NEST的批量请求(Bulk API),通过脚本遍历嵌套数组,完成匹配更新与新增逻辑。

1. 定义C#实体类

对应文档结构定义实体:

public class MarketDocument
{
    public int Id { get; set; }
    public string Description { get; set; }
    public decimal SalesPrice { get; set; }
    public decimal Cost { get; set; }
    public List<HistoryItem> History { get; set; }
}

public class HistoryItem
{
    public DateTime HistoryDate { get; set; }
    public int Quantity { get; set; }
}

2. 批量更新代码实现

构建批量更新请求,为每个指定ID的文档编写对应的更新脚本:

// 假设已初始化ElasticClient实例
var client = new ElasticClient(settings);

// 准备待更新数据集:Key为文档ID,Value为需要更新/新增的HistoryItem列表
var updateTasks = new Dictionary<int, List<HistoryItem>>
{
    {
        1,
        new List<HistoryItem>
        {
            new HistoryItem { HistoryDate = new DateTime(2020, 2, 1), Quantity = 9 },
            new HistoryItem { HistoryDate = new DateTime(2020, 3, 1), Quantity = 11 }
        }
    },
    {
        2,
        new List<HistoryItem>
        {
            new HistoryItem { HistoryDate = new DateTime(2020, 2, 1), Quantity = 20 },
            new HistoryItem { HistoryDate = new DateTime(2020, 3, 1), Quantity = 15 }
        }
    }
};

// 构建批量请求
var bulkRequest = new BulkRequest();
bulkRequest.Operations = new List<IBulkOperation>();

foreach (var task in updateTasks)
{
    var docId = task.Key;
    var historyUpdates = task.Value;

    // 编写Painless脚本:遍历history数组,匹配日期则更新,未匹配则新增
    var script = new InlineScript(@"
        def updates = params.updates;
        for (update in updates) {
            def found = false;
            for (item in ctx._source.history) {
                if (item.historydate == update.historydate) {
                    item.quantity = update.quantity;
                    found = true;
                    break;
                }
            }
            if (!found) {
                ctx._source.history.add(update);
            }
        }
    ")
    {
        Params = new Dictionary<string, object>
        {
            { "updates", historyUpdates.Select(h => new { historydate = h.HistoryDate.ToString("yyyy-MM-dd"), quantity = h.Quantity }) }
        }
    };

    // 添加更新操作到批量请求
    bulkRequest.Operations.Add(new UpdateOperation<MarketDocument, object>(docId)
    {
        Script = script
    });
}

// 执行批量更新
var response = client.Bulk(bulkRequest);

// 检查执行结果
if (response.IsValid)
{
    Console.WriteLine("批量更新成功");
}
else
{
    Console.WriteLine($"批量更新失败: {response.ServerError?.Error?.Reason}");
}

关键说明

  1. 脚本逻辑:
    • 遍历传入的更新参数updates,对每个待更新的日期,先检查原history数组中是否存在匹配项
    • 存在则直接修改quantity值;不存在则调用add方法新增该记录
  2. 日期格式:脚本中统一使用yyyy-MM-dd格式匹配,确保与文档中存储的日期字符串格式一致
  3. 批量请求:通过NEST的BulkRequest将多个更新操作打包执行,提升效率
  4. 映射适配:如果history字段在Elasticsearch中设置为nested类型,脚本逻辑依然适用,无需额外修改

内容的提问来源于stack exchange,提问作者user1887852

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 05:48:22