在 RavenDB 索引中查询单独的集合(WHERE IN)

Query separate collection in RavenDB Index (WHERE IN)

使用 RavenDB v4.2 或更高版本,我想设置一个查询另一个集合的索引。基本上,在索引的映射部分重现一个 WHERE IN 子句。

以下模型代表两个系列。这里每个 User 都有一个设备 ID 的集合:

class Device {
    public string Id { get; set; }
    public string Name { get; set; }
}

class User {
    public string Id { get; set; }
    public string BlogPostId { get; set; }
    public List<string> DeviceIds { get; set; } 
}

现在将以下索引作为我要实现的目标的示例:

public class DeviceIndex : AbstractIndexCreationTask<Device, DeviceIndex.Result>
{
    public class Result
    {
        public string Id { get; set; }
        public string DeviceName { get; set; }
        public bool HasUser { get; set; }
        public int UserCount { get; set; }
    }
    public DeviceIndex()
    {
        Map = devices => from d in devices
                         select new Result
                         {
                             Id = d.Id,
                             DeviceName = d.Name,

                             HasUser = ... ?, // How to get this from Users collection?
                             UserCount = ... ? // same...

                         };

    }

如何在此索引中填写 HasUser true/false 和 UserCount 属性?例如。我如何在这里查询 'User' 集合?

请注意,为简洁起见,此示例已被严重简化。我对解决方法或更改其背后的逻辑不太感兴趣。

如果您在设备中有一个用户列表class
List<string> Users
一个包含来自 Users 集合的文档 ID 的列表,然后您可以 索引这些相关文档。

见: https://demo.ravendb.net/demos/csharp/related-documents/index-related-documents

或者反其道而行之,
Users 集合上创建索引,并索引相关的 Device info


在不改变当前模型的情况下,
您可以创建一个 Multi-Map Index 来索引来自不同集合的数据。

https://ravendb.net/docs/article-page/4.2/csharp/indexes/multi-map-indexes

https://ravendb.net/docs/article-page/4.2/csharp/studio/database/indexes/create-multi-map-index

https://ravendb.net/learn/inside-ravendb-book/reader/4.0/10-static-indexes-and-other-advanced-options#querying-many-sources-at-once-with-multimap-indexes

正如@Danielle 提到的,您需要使用 mutli-map-index 并减少结果。 这是一个工作示例

public class DeviceIndex : AbstractMultiMapIndexCreationTask<DeviceIndex.Result>
    {
        public class Result
        {
            public string Id { get; set; }
            public string DeviceName { get; set; }
            public bool HasUser { get; set; }
            public int UserCount { get; set; }
        }
        public DeviceIndex()
        {
            AddMap<User>(users => from u in users
                                  from deviceId in u.DeviceIds
                                  let d = LoadDocument<Device>(deviceId)
                                select new Result
                                {
                                    Id = d.Id,
                                    HasUser = true,
                                    UserCount = 1,
                                    DeviceName = d.Name,
                                });
            AddMap<Device>(devices => from d in devices
                                      select new Result
                                      {
                                          Id = d.Id,
                                          HasUser = false,
                                          UserCount = 0,
                                          DeviceName = d.Name,
                                      });

            Reduce = results => from result in results
                                group result by new { result.Id } into g
                                select new Result
                                {
                                    Id = g.First().Id,
                                    DeviceName = g.First().DeviceName,
                                    HasUser = g.Any(e => e.HasUser),
                                    UserCount = g.Sum(e => e.UserCount),
                                };

        }
    }

你可以这样称呼它

var result = await _session.Query<DeviceIndex.Result, DeviceIndex>().ToListAsync();