我正在通过LINQ / Iqueryable查询CosmosDB。
我有一个方法,该方法的输入中有一个IEnumerable,可以包含很多元素。
所需查询是
SELECT * FROM table WHERE field LIKE '%input1%' OR field1 LIKE '%input2%'
依次类推,列举了每个IEnumerable元素。
IEnumerable<string> filterElements = GetFiltersExample();
IQueryable<ResultObject> theQuery = AzureDocumentClient.CreateDocumentQuery<ResultObject>(
collectionUri, queryOptions);
if (filterElements.Count() > 0)
foreach (string filterElement in filterElements)
{
theQuery = theQuery.Where(doc => doc.id.Contains(filterElement));
}
但是它会生成
SELECT * FROM table WHERE (CONTAINS(field, 'input1') AND CONTAINS(field, 'input2'))
如果LINQ不会自动将它们置于AND条件(并且由于里面没有该字符串可能会导致结果返回空,因为它不符合条件),这应该起作用。
如何在“或”条件而非“与”条件下进行操作?
我尝试使用PredicateBuilder,但是它没有用,因为它引发了有关无法启动Invoke方法的异常。
这就是我所做的:
var predicate = PredicateBuilder.True<ReturnObj>();
if (elements.Count() > 0)
foreach (string element in elements)
{
predicate = predicate.Or(elem => elem.id.Contains(element));
}
即使使用字符串列表扫描THIS之类的查询元素,我也尝试过各种包含方法
Linq坚持使用AND连接所有条件,因此除非您手动创建LINQ查询,否则它永远不会匹配多个结果:
.Where(condition1 || condition2 || condition3.....)
如何执行此操作?太不可思议了,我对如此缺乏功能的消极方式感到惊讶
答案 0 :(得分:1)
如果您使用的是LinqKit,则可以在AsExpandable
上使用IQueryable
,以便将所有表达式的调用扩展为使用表达式的实际主体,而不是Invoke(element)
。例如,如果您具有这样的表达式:
Expresssion<Func<int, bool>> expr = n => n == 1;
以及类似的查询:
var query = (EnumerableQuery<bool>)new[] { 1 }.AsQueryable().Select(n => d.Invoke(n))
表达式树本身将包含Invoke
方法,此LINQ提供程序不支持该方法。但是,当您使用AxExpandable
时:
var expQuery = (ExpandableQuery<bool>)new[] { 1 }.AsQueryable().AsExpandable().Select(n => d.Invoke(n))
表达式树将包含正文n => n == 1
,而没有Invoke
方法。
所以在您的情况下:
IQueryable<ResultObject> theQuery = AzureDocumentClient
.CreateDocumentQuery<ResultObject>(collectionUri, queryOptions)
.AsExpandable()
.Where(e => predicate.Invoke(e);
应该做到这一点。
或者,如果可能的话,您可以使用不带Invoke
的表达式:
.Where(predicate)
因此不需要AsExpandable
。
答案 1 :(得分:1)
很高兴您通过使用查询字符串找到了解决方法。我只是对您观察到的行为发表一些评论。
答案 2 :(得分:0)
我最终使用字符串concat进行了老式处理,因为我在项目中只有一次查询,所以我不想使用外部库:
StringBuilder query = new StringBuilder("SELECT * From TheCollection WHERE ");
if (idsToCheck.Count() > 0)
foreach (string idGuid in idsToCheck)
{
query.Append($" CONTAINS(TheCollection.id, '{idGuid}') OR ");
}
string builtQuery = query.ToString();
builtQuery = builtQuery.Substring(0, builtQuery.Length - 4);
IQueryable<ResultObject> Query = client.CreateDocumentQuery<ResultObject>(
collectionUri, queryOptions);
return Query.ToList();
工作得很好;)