2011-06-01 71 views
27

我正在研究概念验证代码,以基于提供给我正在撰写的高度特定搜索Web服务的关键字动态生成CAML。我没有使用SharePoint提供的搜索Web服务来提供此证明。我已经这样做了,我正在努力实现。从我所有的研究中,我无法找到一个我试图实现的关键示例,即检查多个字段的多个值。是的,我已经看到了我的答案,包括这个:Need help on building CAML Query带嵌套AND和OR的多个字段的CAML查询

这样说,如果可能的话,如何在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') 

回答

50

由于您不允许在一个条件组中放置两个以上的条件(并且|),您必须创建一个额外的嵌套组(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> 
+0

谢谢,杰森!我回来看看我的问题,提供一个答案,因为我自己想出来了。不过,我很高兴看到您的答案与我的结果相符,非常感谢您花时间帮助我和其他SO用户。 – Alban 2011-06-01 21:48:32

+0

感谢您的信息。您的示例XML提供了一种很好的方式来检查嵌套的语法。我用它来提出这种方法生成[相当于In运算符](http://stackoverflow.com/questions/11198161/caml-in-operator-equivalent-for-sharepoint-services-3-sharepoint- 2007) – xr280xr 2012-06-25 22:19:43

0

您可以尝试U2U查询生成器http://www.u2u.net/res/Tools/CamlQueryBuilder.aspx可以使用他们的API U2U.SharePoint.CAML.Server.dll和U2U.SharePoint.CAML.Client.dll

我没有用他们,但我肯定它会帮助你实现你的任务。

+13

,除非你知道,它可以提供所要求的结果,你不应该在这里发布的解决方案。使用U2U工具是非常节省时间的,但是您应该提供它生成的代码的工作示例。 – 2012-07-18 18:38:30

0

此代码将动态地嵌套为您生成的表达条款。我有一个场景,其中“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>{{FirstExpression}}{{SecondExpression}}</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>{{FirstExpression}}{{SecondExpression}}</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; 
     } 
    } 
+0

您是否搜索过嵌套或caml查询限制?可能会导致此代码出现问题。 – 2017-01-10 07:29:17