如果数组 属性 包含给定列表中的任何项目,如何查询 Cosmos DB?
How to query Cosmos DB if array property contains any item from a given list?
如果你有一个像这样的实体class,它存储在你的 cosmos 数据库中
public class SomeItem
{
public Guid Id { get; set; }
public IReadOnlyList<string> AffectedUsers { get; set; }
}
在您的代码中,您会收到一个用户列表,您必须查询其中列出的所有项目:
var cosmosClient = new CosmosClient("https://test.local/", "Tm9LZXk=");
var container = cosmosClient.GetContainer("123", "456");
// A list of users where we like to get all items, where any of them is listed in affected users.
var someUsers = Enumerable.Range(1, 5).Select(i => $"User {i}").ToList();
// The query that should check if any user of the above list is within affectedUsers
var query = container.GetItemLinqQueryable<SomeItem>()
// How to check for any element in someUsers is within affectedUsers dynamically?
.Where(item => item.AffectedUsers.Contains(someUsers[0]));
var definition = query.ToQueryDefinition();
var text = definition.QueryText;
Console.WriteLine(text);
要解决此问题,需要一些基于 LinqKit 的魔术代码:
public static class QueryableExtensions
{
public static IQueryable<T> WhereAny<T, U>(this IQueryable<T> source, IEnumerable<U> items, Expression<Func<T, U, bool>> expression)
{
var predicate = PredicateBuilder.New<T>();
foreach (var item in items)
{
Expression<Func<T, bool>> comparison = p => expression.Invoke(p, item);
predicate = predicate.Or(comparison.Expand());
}
return source.Where(predicate);
}
}
在您的工具箱中使用此方法,您可以按如下方式编写查询:
var query = container.GetItemLinqQueryable<SomeItem>()
.WhereAny(someUsers, (item, user) => item.AffectedUsers.Contains(user));
生成的 cosmos 查询将是:
SELECT VALUE root FROM root WHERE ((((ARRAY_CONTAINS(root["AffectedUsers"], "User 1")
OR ARRAY_CONTAINS(root["AffectedUsers"], "User 2"))
OR ARRAY_CONTAINS(root["AffectedUsers"], "User 3"))
OR ARRAY_CONTAINS(root["AffectedUsers"], "User 4"))
OR ARRAY_CONTAINS(root["AffectedUsers"], "User 5"))
如果你有一个像这样的实体class,它存储在你的 cosmos 数据库中
public class SomeItem
{
public Guid Id { get; set; }
public IReadOnlyList<string> AffectedUsers { get; set; }
}
在您的代码中,您会收到一个用户列表,您必须查询其中列出的所有项目:
var cosmosClient = new CosmosClient("https://test.local/", "Tm9LZXk=");
var container = cosmosClient.GetContainer("123", "456");
// A list of users where we like to get all items, where any of them is listed in affected users.
var someUsers = Enumerable.Range(1, 5).Select(i => $"User {i}").ToList();
// The query that should check if any user of the above list is within affectedUsers
var query = container.GetItemLinqQueryable<SomeItem>()
// How to check for any element in someUsers is within affectedUsers dynamically?
.Where(item => item.AffectedUsers.Contains(someUsers[0]));
var definition = query.ToQueryDefinition();
var text = definition.QueryText;
Console.WriteLine(text);
要解决此问题,需要一些基于 LinqKit 的魔术代码:
public static class QueryableExtensions
{
public static IQueryable<T> WhereAny<T, U>(this IQueryable<T> source, IEnumerable<U> items, Expression<Func<T, U, bool>> expression)
{
var predicate = PredicateBuilder.New<T>();
foreach (var item in items)
{
Expression<Func<T, bool>> comparison = p => expression.Invoke(p, item);
predicate = predicate.Or(comparison.Expand());
}
return source.Where(predicate);
}
}
在您的工具箱中使用此方法,您可以按如下方式编写查询:
var query = container.GetItemLinqQueryable<SomeItem>()
.WhereAny(someUsers, (item, user) => item.AffectedUsers.Contains(user));
生成的 cosmos 查询将是:
SELECT VALUE root FROM root WHERE ((((ARRAY_CONTAINS(root["AffectedUsers"], "User 1")
OR ARRAY_CONTAINS(root["AffectedUsers"], "User 2"))
OR ARRAY_CONTAINS(root["AffectedUsers"], "User 3"))
OR ARRAY_CONTAINS(root["AffectedUsers"], "User 4"))
OR ARRAY_CONTAINS(root["AffectedUsers"], "User 5"))