具有多个字段的嵌套 AND 和 OR 的 CAML 查询
Posted
技术标签:
【中文标题】具有多个字段的嵌套 AND 和 OR 的 CAML 查询【英文标题】:CAML query with nested ANDs and ORs for multiple fields 【发布时间】:2011-09-06 10:11:35 【问题描述】:我正在研究概念验证代码,以根据提供给我正在编写的高度特定的搜索 Web 服务的关键字动态生成 CAML。我没有使用 SharePoint 提供的搜索 Web 服务来证明这一点。我已经为我想要实现的目标这样做了。从我所有的研究中,我找不到我想要实现的一个紧密的例子,即检查多个字段的多个值。是的,我已经在寻找答案了,包括这个:Need help on building CAML Query。
话虽如此,如果可能的话,如何用 CAML 编写以下类似 SQL 的查询?
SELECT FirstName, LastName, Description, Profile
FROM SomeFakeTable
WHERE (FirstName = 'John' OR LastName = 'John' OR Description = 'John' OR Profile='John')
AND (FirstName = 'Doe' OR LastName = 'Doe' OR Description = 'Doe' OR Profile='Doe')
AND (FirstName = '123' OR LastName = '123' OR Description = '123' OR Profile='123')
【问题讨论】:
【参考方案1】:由于不允许在一个条件组中放置两个以上的条件(And | Or),因此您必须创建一个额外的嵌套组(MSDN)。表达式A AND B AND C
如下所示:
<And>
A
<And>
B
C
</And>
</And>
您的类似 SQL 的示例已翻译为 CAML(希望带有匹配的 XML 标记;)):
<Where>
<And>
<Or>
<Eq>
<FieldRef Name='FirstName' />
<Value Type='Text'>John</Value>
</Eq>
<Or>
<Eq>
<FieldRef Name='LastName' />
<Value Type='Text'>John</Value>
</Eq>
<Eq>
<FieldRef Name='Profile' />
<Value Type='Text'>John</Value>
</Eq>
</Or>
</Or>
<And>
<Or>
<Eq>
<FieldRef Name='FirstName' />
<Value Type='Text'>Doe</Value>
</Eq>
<Or>
<Eq>
<FieldRef Name='LastName' />
<Value Type='Text'>Doe</Value>
</Eq>
<Eq>
<FieldRef Name='Profile' />
<Value Type='Text'>Doe</Value>
</Eq>
</Or>
</Or>
<Or>
<Eq>
<FieldRef Name='FirstName' />
<Value Type='Text'>123</Value>
</Eq>
<Or>
<Eq>
<FieldRef Name='LastName' />
<Value Type='Text'>123</Value>
</Eq>
<Eq>
<FieldRef Name='Profile' />
<Value Type='Text'>123</Value>
</Eq>
</Or>
</Or>
</And>
</And>
</Where>
【讨论】:
谢谢,杰森!我回来访问我的问题以提供答案,因为我自己想通了。但是,我很高兴看到您的回答与我的结果相符,非常感谢您花时间帮助我和其他 SO 用户。 感谢您的帖子。您的示例 XML 提供了一种很好的方法来仔细检查嵌套语法。我用它想出了这个生成equivalent to the In operator的方法【参考方案2】:你可以试试 U2U Query Builder http://www.u2u.net/res/Tools/CamlQueryBuilder.aspx 你可以使用他们的 API U2U.SharePoint.CAML.Server.dll 和 U2U.SharePoint.CAML.Client.dll
我没有使用它们,但我相信它会帮助您完成任务。
【讨论】:
您不应该在此处发布解决方案,除非您知道它可以提供所要求的结果。使用 U2U 工具可以节省大量时间,但您应该提供它生成的代码的工作示例。【参考方案3】:此代码将使用嵌套子句为您动态生成表达式。我有一个场景,其中 "OR" 的数量是未知的,所以我使用下面的。用法:
private static void Main(string[] args)
var query = new PropertyString(@"<Query><Where>WhereClauses</Where></Query>");
var whereClause =
new PropertyString(@"<Eq><FieldRef Name='ID'/><Value Type='Counter'>NestClauseValue</Value></Eq>");
var andClause = new PropertyString("<Or>FirstExpressionSecondExpression</Or>");
string[] values = "1", "2", "3", "4", "5", "6";
query["WhereClauses"] = NestEq(whereClause, andClause, values);
Console.WriteLine(query);
这是代码:
private static string MakeExpression(PropertyString nestClause, string value)
var expr = nestClause.New();
expr["NestClauseValue"] = value;
return expr.ToString();
/// <summary>
/// Recursively nests the clause with the nesting expression, until nestClauseValue is empty.
/// </summary>
/// <param name="whereClause"> A property string in the following format: <Eq><FieldRef Name='Title'/><Value Type='Text'>NestClauseValue</Value></Eq>"; </param>
/// <param name="nestingExpression"> A property string in the following format: <And>FirstExpressionSecondExpression</And> </param>
/// <param name="nestClauseValues">A string value which NestClauseValue will be filled in with.</param>
public static string NestEq(PropertyString whereClause, PropertyString nestingExpression, string[] nestClauseValues, int pos=0)
if (pos > nestClauseValues.Length)
return "";
if (nestClauseValues.Length == 1)
return MakeExpression(whereClause, nestClauseValues[0]);
var expr = nestingExpression.New();
if (pos == nestClauseValues.Length - 2)
expr["FirstExpression"] = MakeExpression(whereClause, nestClauseValues[pos]);
expr["SecondExpression"] = MakeExpression(whereClause, nestClauseValues[pos + 1]);
return expr.ToString();
else
expr["FirstExpression"] = MakeExpression(whereClause, nestClauseValues[pos]);
expr["SecondExpression"] = NestEq(whereClause, nestingExpression, nestClauseValues, pos + 1);
return expr.ToString();
public class PropertyString
private string _propStr;
public PropertyString New()
return new PropertyString(_propStr );
public PropertyString(string propStr)
_propStr = propStr;
_properties = new Dictionary<string, string>();
private Dictionary<string, string> _properties;
public string this[string key]
get
return _properties.ContainsKey(key) ? _properties[key] : string.Empty;
set
if (_properties.ContainsKey(key))
_properties[key] = value;
else
_properties.Add(key, value);
/// <summary>
/// Replaces properties in the format propertyName in the source string with values from KeyValuePairPropertiesDictionarysupplied dictionary.nce you've set a property it's replaced in the string and you
/// </summary>
/// <param name="originalStr"></param>
/// <param name="keyValuePairPropertiesDictionary"></param>
/// <returns></returns>
public override string ToString()
string modifiedStr = _propStr;
foreach (var keyvaluePair in _properties)
modifiedStr = modifiedStr.Replace("" + keyvaluePair.Key + "", keyvaluePair.Value);
return modifiedStr;
【讨论】:
您是否搜索过嵌套或 caml 查询限制?可能会导致此代码出现问题。以上是关于具有多个字段的嵌套 AND 和 OR 的 CAML 查询的主要内容,如果未能解决你的问题,请参考以下文章
具有嵌套查询和 UUID 数组字段的 HQL/JPQL 查询