Запросы CAML: как фильтровать папки из результирующего набора?

Я использую запрос caml для выбора всех документов, которые были изменены или добавлены пользователем. Запрос выполняется рекурсивно на всех дочерних сайтах указанного семейства веб-сайтов.

проблема теперь я не могу избавиться от папок, которые также являются частью результирующего набора. Пока я фильтрую их из result datatable. Но мне интересно: можно ли отфильтровать папки из результирующего набора только с помощью caml?

8 ответов


этот CAML на самом деле делает трюк:

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

это не даст вам никаких папок.


Итак, я понял это :) Вы можете использовать FieldRef= 'ContentType' в запросе caml и указать тип контента, который вы хотите выбрать или исключить из select.

поэтому в моем случае я добавил Это условие к моему выражению caml:

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

Примечание.: Есть проблемы в настройке нескольких языков. Имя типа контента может отличаться, поэтому хорошо получить имена типов контента из ресурсы

обновление:

похоже, я был слишком быстр в своих предположениях. Мне нужно отфильтровать все типы contett на основе типа содержимого папки, потому что в наших проектах используются такие типы контента : (

Я не смог создать работоспособный запрос в caml, поэтому я добавил элемент поля просмотра в свой запрос, который выбирает ContentTypeId элемента списка, и я отфильтровываю строки, основанные на типе содержимого папки.

код для этого тривиален, но меня беспокоит, что такая простая задача не может быть выполнена чистым caml.


согласно выходу от CAML Designer (создано Карине Бош и Энди Ван Стинберген и распространяется группой пользователей Belux Information Worker) правильный синтаксис 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

можно заменить на <QueryOptions> тег в CAML с помощью свойства объекта Spquery ViewAttributes, если вы предпочитаете, т. е. $qry.ViewAttributes = “Scope=’RecursiveAll’".

при тестировании этого обязательно повторно создайте экземпляр объекта SPQuery каждый раз, когда вы не можете просто переназначить свойство Query. После выполнения запроса любое новое значение, назначенное свойству Query, игнорируется. Поэтому выполните весь фрагмент PowerShell.


Если вы работаете с папками и используете объект SPQuery, вы также можете использовать поле ViewAttributes для рекурсивного извлечения элемента. Установка значения Scope= "Recursive" будет извлекать элементы из подпапок и не будет извлекать объекты папок в результирующем наборе.

myQuery.ViewAttributes = "Scope=\"Recursive\"";

ответ Дэйва т. не работал для меня, но принимая это как вдохновение вот что я придумал:

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

основная проблема в том, что мы можем знать только ContentTypeId на уровне сайта, потому что когда тип контента добавляется в список / библиотеку, он становится тип содержимого списка и его идентификатор добавляется с другим идентификатором GUID (0x010100...). А вот и нет NotBeginsWith условие в CAML, поэтому мы не можем отфильтровать папки, но мы можем включить документы только какой идентификатор типа контента сайта 0x0101.

решения с FSObjType поле не работает для меня, потому что у меня есть библиотеки с гораздо большим количеством файлов, чем порог, поэтому все поля в запросе должны быть индексированы, и я не нашел способ индексировать это поле.


Это то, что сработало для меня

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

проверьте мой другой ответ запрос CAML, который включает папки в результирующем наборе

простое изменение операторов может дать вам то, что вам нужно

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

Я не уверен, что это сработает.


для меня это сработало как написано ниже:-

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