Consulta de CAML en SharePoint Online View

Tengo una biblioteca muy grande en un entorno de SharePoint Online:> 3000 (conjuntos de documentos) en la carpeta raíz y más de 7000 (conjuntos de documentos, carpetas y documentos) en total. El sistema se basa principalmente en código personalizado: C # CSOM.

En cuanto al rendimiento, el sistema se beneficiaría enormemente de consultar subconjuntos de todo el conjunto de datos, en lugar de los 7000 elementos completos cada vez (mi solución actual carga lotes de 5000 elementos en una ListItemCollection: en mi caso primero 5000 y luego 2000, y luego LINQ realiza las consultas), especialmente teniendo en cuenta que ciertas operaciones están directamente vinculadas a vistas específicas.

Estoy probando la siguiente implementación que se encuentra en un comentario sobre otro hilo .

Microsoft.SharePoint.Client.List list = ctx.Web.Lists.GetByTitle(ListName); ctx.Load(list); ctx.ExecuteQuery(); Microsoft.SharePoint.Client.View view = list.Views.GetByTitle(viewName); ctx.Load(view); ctx.ExecuteQuery(); CamlQuery query = new CamlQuery(); query.ViewXml = view.ViewQuery; ListItemCollection items = list.GetItems(query); ctx.Load(items); ctx.ExecuteQuery(); 

Mi problema es que ListItemCollection se está llenando con todos los elementos de la colección raíz (3000), cuando las vistas elegidas probadas constan de un máximo de 60 elementos.

La view.ViewQuery se completa con este valor:

"<GroupBy Collapse=\"FALSE\" GroupLimit=\"30\"><FieldRef Name=\"CurrentStatus\" /></GroupBy><OrderBy><FieldRef Name=\"CurrentStatus\" Ascending=\"FALSE\" /><FieldRef Name=\"Stage\" /></OrderBy><Where><And><Eq><FieldRef Name=\"Stage\" /><Value Type=\"Text\">Confirm Container</Value></Eq><Eq><FieldRef Name=\"PastTransition\" /><Value Type=\"Boolean\">0</Value></Eq></And></Where>" 

¿Se supone que el código anterior funciona? Si es así, ¿qué pasa? Si no, ¿cuál es otra solución que logra lo mismo?

Comentarios

  • ¿Qué aspecto tiene ViewQuery? como?

Respuesta

¿Está sacando CAML de la vista porque los usuarios podrían actualizar los detalles del filtro? De lo contrario, probablemente la mejor manera de hacerlo sea iniciar la consulta manualmente.

Pruébelo:

query.ViewXml ="<View Scope=\"Recursive\"><Query><Where><And><Eq><FieldRef Name=\"Stage\" /><Value Type=\"Text\">Confirm Container</Value></Eq><Eq><FieldRef Name=\"PastTransition\" /><Value Type=\"Boolean\">0</Value></Eq></And></Where></Query></View>" 

Debido a que su lista tiene> 7k elementos, también debe asegurarse de que uno o ambos de las columnas Stage y PastTransition están indexadas. Puede depender de cuál devuelva el subconjunto más pequeño de datos y en qué orden se evalúan.

Es posible que también deba hacer «RecursiveAll» en lugar de «Recursive», dependiendo de si desea / necesita devolver carpetas. Ver la enumeración del alcance: https://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spviewscope.aspx

Esto debería obtener la lista filtrada. A partir de ahí, su código puede agrupar / ordenar los artículos devueltos.

Actualizar

Dado que los detalles de la consulta deben recopilarse dinámicamente desde las vistas existentes (según sus comentarios a continuación), puede extraer el contenido de la vista existente .ViewQuery e inyectarlo en la vista XML anterior. Esto eliminará y también permitirá que la consulta se ejecute en listas> 5k.

Consulte el código de Jurgen para obtener una solución completa.

Comentarios

  • Funciona así. ¿Significa que configurar una consulta CAML y filtrar en columnas indexadas con un conjunto de datos consultables de más de 5000 elementos, ¿no fallará si el resultado devuelto es menor de 5000? Esta es una alternativa, pero en realidad no es una solución. ¿No hay forma de obtener ¿Desde la Vista? Me gustaría tener la consulta creada dinámicamente desde varias vistas y no tener que volver a crear la configuración de la vista en la consulta CAML cada vez, si eso es posible, por supuesto. ¡Sin embargo, este es un muy buen comienzo! Así que gracias mucho 🙂
  • @JurgenCuschieri: Debería funcionar bien si hay más de 5K elementos de la lista. No estoy seguro de ' entiendo completamente su caso de uso, pero si desea extraer los detalles del filtro de la vista (o vistas) de forma dinámica, probablemente podría hacerlo extrayendo la < Query > parte de la vista ' s CAML e inyectarlo dinámicamente en < Ver Scrope = " Recusivo " > < / Ver >.
  • Yo ' intentaré eso y volveré a ti. Para hacerlo un poco más claro, tengo un sistema implementado con muchas consultas diferentes. La consulta CAML se utiliza para cargar lotes de 5000 elementos en una colección de elementos de lista. LINQ se utiliza para consultar la ListItemCollection resultante. No hace falta decir que la operación tarda mucho en devolver un resultado. Todos (o casi todos) los escenarios están teóricamente ligados a una vista. lo que significa que el conjunto de datos consultables se puede minimizar a los mismos resultados de vista. Entonces, si la consulta de caml se puede completar automáticamente desde la consulta ' s automáticamente, ¿tiene más sentido, no?
  • Las vistas definen etapas particulares dentro de una empresa cliente. ' s proceso empresarial. las operaciones de consulta CAML que se utilizan específicamente dentro de una etapa, por lo tanto, pueden utilizar la misma consulta que la vista. Esto refinará el conjunto de datos consultables, en lugar de usar todos los elementos de la lista cada vez.
  • ¡Genial! Me alegro de que haya funcionado. Nosotros, los desarrolladores de SharePoint, tenemos que mantenernos unidos … 🙂

Responder

La siguiente es mi solución final, basado en la respuesta de @Jim Barntish.

Microsoft.SharePoint.Client.List list = ctx.Web.Lists.GetByTitle(ListName); ctx.Load(list); ctx.ExecuteQuery(); Microsoft.SharePoint.Client.View view = list.Views.GetByTitle(viewName); ctx.Load(view); ctx.ExecuteQuery(); CamlQuery query = new CamlQuery(); query.ViewXml = view.ViewQuery; int pFrom = query.ViewXml.IndexOf("<Where>") + "<Where>".Length; int pTo = query.ViewXml.LastIndexOf("</Where>"); string whereClause = query.ViewXml.Substring(pFrom, pTo - pFrom); string queryStr = "<View Scope=\"Recursive\"><Query><Where>" + whereClause + "</Where></Query></View>"; query.ViewXml = queryStr; ListItemCollection items = list.GetItems(query); ctx.Load(items); ctx.ExecuteQuery(); 

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *