在 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
正如@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();
使用 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' 集合?
请注意,为简洁起见,此示例已被严重简化。我对解决方法或更改其背后的逻辑不太感兴趣。
如果您在设备中有一个用户列表classList<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
正如@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();