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

RavenDB LINQ查询问题:如何实现输入与文档集合的交集查询

问题描述

我在数据库中定义了如下Element实体:

public class Element
{
    public string Id { get; set; } = string.Empty;

    public IEnumerable<string> ExternalIds { get; set; } = Enumerable.Empty<string>();
    
    ...
}

为查询拥有至少一个匹配ExternalId的Element文档,我创建了如下扇出索引:

public class Elements_ByExternalIds : AbstractIndexCreationTask<Element>
{
    public class Result
    {
        public string? ExternalId { get; set; }

        public string? ElementId { get; set; }
    }

    public Elements_ByExternalIds()
    {
        Map = elements => from element in elements
                          from externalId in element.ExternalIds
                          select new Result
                          {
                              ExternalId = externalId,
                              ElementId = element.Id
                          };
    }
}

我需要在仓储中实现查询:传入一组externalIds,返回自身ExternalIds集合包含其中任意值的Element文档(输入与文档集合交集非空)。我尝试了两种查询写法:

public async Task<Result<IEnumerable<Element>>> GetElementsWhichContainExternalIds(IEnumerable<string> externalIds)
{
    try
    {
        var elements = await _session
            .Query<Elements_ByExternalIds.Result, Elements_ByExternalIds>()
            .Where(element => externalIds.Contains(element.externalId)) // 第一次尝试
            //.Where(element => externalIds.Any(externalId => externalId == element.ExternalId)) // 第二次尝试
            .Select(elements =>
                new Elements_ByExternalIds.Result()
                {
                    ExternalIds = elements.ExternalIds,
                    ElementId = elements.ElementId
                })
            .ToListAsync(cancellationToken);


        return Result.Success(elements);
    }
    catch (Exception ex)
    {
        return Result.Failure<IEnumerable<Element>>($"Failed {ex.Message}");
    }
}

但两种写法均报错:

Could not understand expression

请问如何在RavenDB索引中执行交集查询,其中一个集合来自应用输入,另一个在RavenDB文档中?我的思路是创建扇出索引,尝试匹配索引单个值与闭包集合。


解决方案

1. 修正自定义索引的查询逻辑

你的查询报错有两个核心原因:一是索引结果类Result中不存在ExternalIds属性,却在Select中试图访问;二是闭包集合的匹配语法需要调整。修正后的代码如下:

public async Task<Result<IEnumerable<Element>>> GetElementsWhichContainExternalIds(IEnumerable<string> externalIds, CancellationToken cancellationToken)
{
    try
    {
        // 通过扇出索引找到所有匹配的ElementId,去重避免重复条目
        var matchingElementIds = await _session
            .Query<Elements_ByExternalIds.Result, Elements_ByExternalIds>()
            .Where(x => externalIds.Contains(x.ExternalId))
            .Select(x => x.ElementId)
            .Distinct()
            .ToListAsync(cancellationToken);

        // 加载对应的Element实体文档
        var elements = await _session.LoadAsync<Element>(matchingElementIds, cancellationToken);

        return Result.Success(elements);
    }
    catch (Exception ex)
    {
        return Result.Failure<IEnumerable<Element>>($"Failed {ex.Message}");
    }
}

2. 简化方案:使用动态查询(无需自定义索引)

RavenDB支持直接对文档集合属性做交集查询,无需手动创建扇出索引,代码更简洁:

public async Task<Result<IEnumerable<Element>>> GetElementsWhichContainExternalIds(IEnumerable<string> externalIds, CancellationToken cancellationToken)
{
    try
    {
        var elements = await _session
            .Query<Element>()
            .Where(element => element.ExternalIds.Any(id => externalIds.Contains(id)))
            .ToListAsync(cancellationToken);

        return Result.Success(elements);
    }
    catch (Exception ex)
    {
        return Result.Failure<IEnumerable<Element>>($"Failed {ex.Message}");
    }
}

RavenDB会自动为ExternalIds集合生成合适的动态索引,满足交集匹配需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 06:47:45