【问题标题】:RavenDB query documents NOT referenced in related documentRavenDB 查询文档未在相关文档中引用
【发布时间】:2025-12-05 08:35:01
【问题描述】:
public class LedgerItem
{
    public string Id { get; set; }
    ...
}

public class Order
{
    ...
    public IList<OrderLine> OrderLines { get; private set; }
    ...
}

public class OrderLine
{
    ...
    public List<string> LedgerItemIds { get; set; }
    ...
}

我需要在任何 Order.OrderLines.LedgerItemIds 中找到 Id 未引用的所有 LedgerItem。

到目前为止,我已经尝试创建一个 Multi-Map/Reduce 索引以从 LedgerItems 和 Orders 中选择所有 LedgerItems,然后按 LedgerItemId 进行归约并汇总计数。 然后我的计划是按 Count == 1 进行查询,因为这意味着它在组中只存在一次。

public class LedgerItemResult
{
    public string Id { get; set; }
    public DateTime CreatedDate { get; set; }
    public string ProTeriaCustomerId { get; set; }
    public string Collection { get; set; }
    public int Count { get; set; }
}

public class LedgerItemsFromLedgerItemsAndOrdersGroupById : AbstractMultiMapIndexCreationTask<LedgerItemResult>
{
    public LedgerItemsFromLedgerItemsAndOrdersGroupById()
    {
        AddMap<LedgerItem>(
            ledgeritems => from ledgeritem in ledgeritems
            where (decimal)ledgeritem.Amount < 0m
            select new
            {
                Id = ledgeritem.Id,
                CreatedDate = ledgeritem.TimeStamp,
                ProTeriaCustomerId = ledgeritem.ProTeriaCustomerId,
                Collection = MetadataFor(ledgeritem)["Raven-Entity-Name"].ToString(),
                Count = 1
            }
        );

        AddMap<Order>(
            orders => from order in orders
            from orderline in order.OrderLines
            from ledgeritemid in orderline.LedgerItemIds
            select new
            {
                Id = ledgeritemid,
                CreatedDate = order.CreatedDateTime,
                ProTeriaCustomerId = order.ProTeriaCustomerId,
                Collection = MetadataFor(order)["Raven-Entity-Name"].ToString(),
                Count = 1
            }
        );

        Reduce = results =>
            from result in results
            group result by result.Id into g
            select new LedgerItemResult
            {
                Id = g.First().Id,
                CreatedDate = g.First().CreatedDate,
                ProTeriaCustomerId = g.First().ProTeriaCustomerId,
                Collection = g.First().Collection,
                Count = g.Sum(x => x.Count)
            };

        Stores.Add(x => x.Id, FieldStorage.Yes);
        Stores.Add(x => x.CreatedDate, FieldStorage.Yes);
        Stores.Add(x => x.ProTeriaCustomerId, FieldStorage.Yes);
        Stores.Add(x => x.Collection, FieldStorage.Yes);

        MaxIndexOutputsPerDocument = 250;
    }
}

但这似乎无法正常工作。我尝试在 Count == 1 和 Count == 2 上进行查询,结果 Count == 1 的结果太多了,我手动检查了返回的 LedgerItemId 之一,看看它是否真的被 Order 引用了,虽然它是不应该。

可能有更简单的方法可以实现这一点,但我仍然有点习惯于用 SQL 来思考。

我希望找到一种方法来实现这一点,这样我就可以在 Management Studio 中使用 Lucene 语法以及在代码中使用 LiINQ 来查询索引。

【问题讨论】:

    标签: ravendb


    【解决方案1】:

    原来我是在正确的轨道上,但被欺骗了一段时间,因为磁盘快满了。它可能越过了“磁盘空间太少时停止索引”的阈值——索引正在运行并且创建的索引不一致。

    【讨论】: