web-dev-qa-db-fra.com

Requêtes CAML: comment filtrer les dossiers du jeu de résultats?

J'utilise caml query pour sélectionner tous les documents qui ont été modifiés ou ajoutés par l'utilisateur. La requête s'exécute de manière récursive sur tous les sous-sites de la collection de sites spécifiée.

Maintenant, le problème est que je ne peux pas me débarrasser des dossiers qui font également partie du jeu de résultats. Pour le moment je les filtre du résultat datatable. Mais je me demande: est-il possible de filtrer les dossiers du jeu de résultats en utilisant simplement caml?

21
drax

Ce CAML fait le tour:

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

cela ne vous donnera aucun dossier.

24
Johan Leino

Donc, je l'ai compris:) Vous pouvez utiliser FieldRef = 'ContentType' dans votre requête caml et spécifier un type de contenu que vous souhaitez sélectionner ou exclure.

Donc, dans mon cas, j'ai ajouté cette condition à mon expression caml:

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

REMARQUE: La configuration en plusieurs langues pose des problèmes. Le nom du type de contenu peut être différent, il est donc utile d'obtenir les noms des types de contenu à partir de ressources.

METTRE À JOUR:

Il semble que j'ai été trop rapide dans mes hypothèses. Je dois filtrer tous les types de contett en fonction du type de contenu du dossier, car dans nos projets, de tels types de contenu sont utilisés :(

Je ne pouvais pas créer de requête utilisable dans caml, j'ai donc ajouté à ma requête un élément de champ de visualisation qui sélectionne ContentTypeId de l'élément de liste et des lignes filtrées en fonction du type de contenu du dossier.

Code pour faire cela est trivial, mais cela me dérange qu'une telle tâche simple ne puisse pas être accomplie par pure caml.

12
drax

Selon le résultat de CAML Designer (créé par Karine Bosch et Andy Van Steenbergen et distribué par le groupe d’utilisateurs Belux Information Worker User Group), la syntaxe CAML correcte est la suivante:

<Where>
  <Eq>
    <FieldRef Name='FSObjType' />
    <Value Type='Integer'>0</Value>
  </Eq>
</Where>
<QueryOptions>
  <ViewAttributes Scope='RecursiveAll' />
</QueryOptions>

J'ai testé cela dans PowerShell et j'ai obtenu le résultat attendu:

$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

Vous pouvez remplacer la balise <QueryOptions> dans le CAML par la propriété d'objet SPQuery ViewAttributes si vous préférez, à savoir $qry.ViewAttributes = “Scope=’RecursiveAll’".

Lors du test, veillez à ré-instancier l'objet SPQuery à chaque fois, car vous ne pouvez pas simplement réaffecter la propriété Query. Une fois la requête exécutée, toute nouvelle valeur affectée à la propriété Query est ignorée. Exécutez donc tout le fragment PowerShell.

5
JohnC

Si vous travaillez avec des dossiers et que vous utilisez un objet SPQuery, vous pouvez également utiliser le champ ViewAttributes pour permettre la récupération d'éléments récursive. Définir la valeur sur Scope = "Récursif" récupérera les éléments des sous-dossiers et ne récupérera pas les objets de dossier dans le jeu de résultats.

myQuery.ViewAttributes = "Scope=\"Recursive\"";
4
Peter Jacoby

La réponse de Dave T. n'a pas fonctionné pour moi, mais en prenant cela comme inspiration, voici ce que j'ai proposé:

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

Le problème principal est que nous ne pouvons connaître que ContentTypeId au niveau du site, car lorsqu'un type de contenu est ajouté à une liste/bibliothèque, il devient un type de contenu de liste et son ID est ajouté. avec un autre GUID (0x010100 ...). Et il y a no NotBeginsWith condition dans CAML, nous ne pouvons donc pas filtrer les dossiers, mais nous pouvons inclure documents uniquement dont le type id de contenu du site est 0x0101.

Les solutions avec le champ FSObjType ne fonctionnent pas parce que mes bibliothèques contiennent beaucoup plus de fichiers qu'un seuil; tous les champs de la requête doivent donc être indexés et je n'ai pas trouvé le moyen d'indexer ce champ. .

2
Rustam

C'est ce qui a fonctionné pour moi

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

Vérifier mon autre réponse Requête CAML incluant des dossiers dans le jeu de résultats

Changer simplement les opérateurs peut vous donner ce dont vous avez besoin

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

Je ne sais pas si ça va marcher.

0
Dave T.

Pour moi aussi cela a fonctionné comme écrit ci-dessous: -

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