CAML查询:如何从结果集中过滤文件夹?

22

我正在使用Caml查询,选择由用户修改或添加的所有文档。查询在指定网站集的所有子站点上递归运行。

现在问题是我无法摆脱结果集中也包含的文件夹。目前,我从结果数据表中过滤它们。但是我想知道:是否可能仅通过使用Caml来过滤掉结果集中的文件夹?

8个回答

31

这个CAML确实有用:

<Where>
    <Eq>
        <FieldRef Name='FSObjType' />
        <Value Type='Integer'>0</Value>
    </Eq>
</Where>

这不会为你提供任何文件夹。


在寻找仅限文件夹的查询时,我看到了这个主题。这个CAML查询在SharePoint 2013上实际上适用于我。当然,我将int更改为1,但如果你只想要文件,则0也很好用。 - Martin
2
这个是从CSOM工作的 <Where><Eq><FieldRef Name="FSObjType" /><Value Type="Integer">0</Value></Eq></Where> - Oleg Savelyev
3
为了仅获取文档,您必须使用 Scope='Recursive' 而不是 Scope='RecursiveAll' 作为 ViewAttributes。Scope='RecursiveAll' 将始终从库中返回文件和文件夹。 - Burst

13

所以,我想通了 :) 您可以在caml查询中使用FieldRef='ContentType',并指定要选择或从选择中排除的内容类型。

所以在我的情况下,我已经将这个条件添加到我的caml表达式中:

<Neq><FieldRef Name='ContentType' /><Value Type='Text'>Folder</Value></Neq>

注意: 在多语言设置中存在问题。内容类型的名称可能不同,因此最好从资源中获取内容类型的名称。

更新:

看来我太急于做出假设了。我需要基于文件夹内容类型过滤掉所有内容类型,因为在我们的项目中使用了这样的内容类型 :(

我无法在caml中创建可工作的查询,因此我将视图字段元素添加到我的查询中,该元素选择列表项的ContentTypeId,并过滤掉基于文件夹内容类型的行。

执行此操作的代码很简单,但令人困扰的是,如此简单的任务不能通过纯caml完成。


4
我下投了你的回答,因为Johan Leino的回答适用于SharePoint 2013。那应该是现在被接受的答案。 - Martin
我点赞了这个帖子,因为一些奇怪的原因,对于 $filter=FSObjType eq 0 的 REST 调用失败了。ContentTypeId 可以工作,但看起来像是 hack。 - nawfal
一些信息在这里:http://sharepoint.stackexchange.com/questions/124846/rest-with-filter-for-list-items-in-sharepoint-2013 - nawfal

6
根据由Karine Bosch和Andy Van Steenbergen创建并由Belux信息工作者用户组分发的CAML Designer输出,正确的CAML语法为:
<Where>
  <Eq>
    <FieldRef Name='FSObjType' />
    <Value Type='Integer'>0</Value>
  </Eq>
</Where>
<QueryOptions>
  <ViewAttributes Scope='RecursiveAll' />
</QueryOptions>

我在 PowerShell 中进行了测试,得到了预期的结果:

$qry = new-object Microsoft.SharePoint.SPQuery
$qry.Query = "<Where><Eq><FieldRef Name='FSObjType' /><Value Type='Integer'>0</Value></Eq></Where><QueryOptions><ViewAttributes Scope='RecursiveAll' /></QueryOptions>"

$items = $lib.GetItems($qry)
$items.Count

你可以使用SPQuery对象属性ViewAttributes替换CAML中的标记,例如$qry.ViewAttributes = “Scope=’RecursiveAll’"。
在测试时,请确保每次重新实例化SPQuery对象,因为您不能简单地重新分配查询属性。一旦查询已被执行,任何新值分配给查询属性都将被忽略。因此,请执行整个PowerShell片段。

5
如果您正在使用文件夹并且使用SPQuery对象,则可能还希望使用ViewAttributes字段以允许递归项检索。将值设置为Scope="Recursive"将从子文件夹中检索项目,并且不会在结果集中检索文件夹对象。
myQuery.ViewAttributes = "Scope=\"Recursive\"";

2

Dave T.的回答对我没有用,但是以此为灵感,我想到了以下解决方法:

<Where>
  <BeginsWith><FieldRef Name="ContentTypeId" />
    <Value Type="ContentTypeId">0x0101</Value>
  </BeginsWith>
</Where>

主要问题在于我们只能在网站级别上知道ContentTypeId,因为当内容类型添加到列表/库中时,它就变成了列表内容类型,并附加另一个GUID(0x010100…)。同时在CAML中没有NotBeginsWith条件,所以我们无法过滤文件夹,但可以包含仅网站内容类型ID为0x0101的文档。
使用FSObjType字段的解决方案对我不起作用,因为我有比阈值更多的文件的库,所以查询中的所有字段都必须被索引,而我还没有找到索引此字段的方法。

0

对我来说,下面的方法也起作用:

<Where><Eq><FieldRef Name='FSObjType' /><Value Type='Integer'>1</Value></Eq></Where>

<Where><Eq><FieldRef Name='FSObjType' /><Value Type='Integer'>1</Value></Eq></Where> - Atul

0

这是对我有效的方法

   <Where>
      <Eq>
         <FieldRef Name='FSObjType' />
         <Value Type='Number'>1</Value>
      </Eq>
   </Where>

0

查看我的其他答案包括结果集的文件夹的CAML查询

简单地更改运算符可能会得到你所需要的东西

<Where>
  <NotIncludes>
    <FieldRef Name='ContentTypeId' />
    <Value Type='ContentTypeId'>0x0120</Value>
  </NotIncludes>
</Where>

我不确定那会不会起作用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接