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

使用Nest与ElasticSearch查询符合生日条件的用户票据

解决Elasticsearch中通过Nest查询指定用户关联票据的问题

索引结构与对应.NET实体类

Elasticsearch索引定义

PUT /customers
{
  "mappings": {
    "properties": {
      "customerId": {
        "type": "integer"
      },
      "name": {
        "type": "keyword"
      },
      "birthday": {
        "type": "date",
        "format": "yyyy-MM-dd"
      }
    }
  }
}

PUT /tickets
{
  "mappings": {
    "properties": {
      "ticketId": {
        "type": "integer"
      },
      "customerId": {
        "type": "integer"
      },
      "winning": {
        "type": "float"
      }
    }
  }
}

.NET实体类

public class Customer
{
    public int CustomerId { get; }
    public string Name { get; }
    public DateTime Birthday { get; }

    public Customer(int customerId, string name, DateTime birthday)
    {
        CustomerId = customerId;
        Name = name;
        Birthday = birthday;
    }
}

public class Ticket
{
    public int TicketId { get; }
    public int CustomerId { get; }
    // 适配ES中float类型的字段映射
    [Number(NumberType.Float)]
    public decimal Winning { get; }

    public Ticket(int ticketId, int customerId, decimal winning)
    {
        TicketId = ticketId;
        CustomerId = customerId;
        Winning = winning;
    }
}

需求

获取所有生日早于1990-01-01的用户所持有的票据。

原代码问题

原代码尝试跨索引做布尔查询,但未通过customerId关联用户和票据,逻辑上只是同时返回符合条件的用户和所有票据,无法得到用户与票据的关联结果;同时使用Search<object>会导致类型映射不安全,难以处理返回数据。

正确实现方案

方案一:分两步查询(逻辑清晰,性能稳定)

先筛选出符合条件的用户ID,再根据ID查询关联票据:

  1. 获取目标用户ID列表
// 查询生日早于1990-01-01的用户,仅返回customerId字段减少数据传输
var customerIdsResponse = client.Search<Customer>(s => s
    .Index("customers")
    .Source(src => src.Include(f => f.CustomerId))
    .Query(q => q
        .DateRange(dr => dr
            .Field(f => f.Birthday)
            .LessThan(new DateTime(1990, 1, 1))
        )
    )
);

var targetCustomerIds = customerIdsResponse.Documents.Select(c => c.CustomerId).ToList();
  1. 根据用户ID查询关联票据
// 查询指定用户持有的所有票据
var ticketsResponse = client.Search<Ticket>(s => s
    .Index("tickets")
    .Query(q => q
        .Terms(t => t
            .Field(f => f.CustomerId)
            .Terms(targetCustomerIds)
        )
    )
);

// 最终结果:符合条件的票据集合
var resultTickets = ticketsResponse.Documents;

方案二:单次子查询(合并为一次请求)

借助Nest的Terms Lookup直接关联用户条件,实现单次查询:

var ticketsResponse = client.Search<Ticket>(s => s
    .Index("tickets")
    .Query(q => q
        .Terms(t => t
            .Field(f => f.CustomerId)
            .Lookup(l => l
                .Index("customers")
                .Id("customerId")
                .Query(lq => lq
                    .DateRange(dr => dr
                        .Field("birthday")
                        .LessThan(new DateTime(1990, 1, 1))
                    )
                )
            )
        )
    )
);

var resultTickets = ticketsResponse.Documents;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 19:53:16