¿Cuál es la mejor manera de recuperar valores distintos/únicos utilizando SPQuery?

StackOverflow https://stackoverflow.com/questions/560550

  •  05-09-2019
  •  | 
  •  

Pregunta

Tengo una lista que se parece a:

Movie          Year
-----          ----
Fight Club     1999
The Matrix     1999
Pulp Fiction   1994

Al usar CAML y el objeto SPQuery, necesito obtener una lista distinta de elementos de la columna Año que completará un control desplegable.

Buscar por allí no parece ser una forma de hacerlo dentro de la consulta CAML.Me pregunto cómo ha hecho la gente para lograr esto.

¿Fue útil?

Solución

Otra forma de hacer esto es usar DataView.ToTable-Method: su primer parámetro es el que diferencia la lista.

            SPList movies = SPContext.Current.Web.Lists["Movies"];
            SPQuery query = new SPQuery();
            query.Query = "<OrderBy><FieldRef Name='Year' /></OrderBy>";

            DataTable tempTbl = movies.GetItems(query).GetDataTable();
            DataView v = new DataView(tempTbl);
            String[] columns = {"Year"};
            DataTable tbl = v.ToTable(true, columns);

Luego puede continuar usando DataTable tbl.

Otros consejos

Si desea enlazar los distintos resultados a una fuente de datos de, por ejemplo, un repetidor y retener el artículo real a través del método e.Item.DataItem los eventos ItemDataBound, la forma DataTable no va a trabajar. En lugar de ello, y además también cuando no querer unirse a un origen de datos, se puede también utilizar LINQ para definir los valores distintos.

// Retrieve the list. NEVER use the Web.Lists["Movies"] option as in the other examples as this will enumerate every list in your SPWeb and may cause serious performance issues
var list = SPContext.Current.Web.Lists.TryGetList("Movies");

// Make sure the list was successfully retrieved
if(list == null) return;

// Retrieve all items in the list
var items = list.GetItems();

// Filter the items in the results to only retain distinct items in an 2D array
var distinctItems = (from SPListItem item in items select item["Year"]).Distinct().ToArray()

// Bind results to the repeater
Repeater.DataSource = distinctItems;
Repeater.DataBind();

Recuerde que, dado que no hay soporte para las consultas de CAML distintas, cada una muestra proporcionada en esta página recuperará todos los elementos de la SPList. Esto puede estar bien para listas más pequeñas, pero para listas con miles de ListItems, esto en serio va a ser un asesino rendimiento. Desafortunadamente no hay manera de conseguir el mismo no más optimizado.

No hay DISTINCT en CAML para poblar el desplegable trate de usar algo como:

foreach (SPListItem listItem in listItems)
    {
        if ( null == ddlYear.Items.FindByText(listItem["Year"].ToString()) )
       {
                   ListItem ThisItem = new ListItem();
                   ThisItem.Text = listItem["Year"].ToString();
                   ThisItem.Value = listItem["Year"].ToString();
                   ddlYear.Items.Add(ThisItem);
        }
   }

supone que su desplegable se llama ddlYear.

Se puede cambiar de SPQuery a SPSiteDataQuery? Usted debe ser capaz de, sin ningún problema.

Después de eso, se puede utilizar el comportamiento ado.net estándar:

SPSiteDataQuery query = new SPSiteDataQuery();
/// ... populate your query here. Make sure you add Year to the ViewFields.

DataTable table = SPContext.Current.Web.GetSiteData(query);

//create a new dataview for our table
DataView view = new DataView(table);

//and finally create a new datatable with unique values on the columns specified

DataTable tableUnique = view.ToTable(true, "Year");

Luego de descubrir cargo después de post acerca de cómo esto era imposible, por fin he encontrado una manera. Esto ha sido probado en SharePoint Online. Aquí es una función que les permite conocer todos los valores únicos de una columna. Sólo es necesario que indique el ID de lista, vista de ID, nombre de la lista interna, y una función de devolución de llamada.

function getUniqueColumnValues(listid, viewid, column,  _callback){
var uniqueVals = [];
$.ajax({
    url: _spPageContextInfo.webAbsoluteUrl + "/_layouts/15/filter.aspx?ListId={" + listid + "}&FieldInternalName=" + column + "&ViewId={" + viewid + "}&FilterOnly=1&Filter=1",
    method: "GET",
    headers: { "Accept": "application/json; odata=verbose" }
    }).then(function(response) {
        $(response).find('OPTION').each(function(a,b){
            if ($(b)[0].value) {
                uniqueVals.push($(b)[0].value);
            }
        });
        _callback(true,uniqueVals);
},function(){
    _callback(false,"Error retrieving unique column values");
});

}

Yo estaba considerando este problema el día de hoy, y la mejor solución que se me ocurrió utiliza el siguiente algoritmo (lo siento, no hay código en el momento):

L is a list of known values (starts populated with the static Choice options when querying fill-in options, for example)
X is approximately the number of possible options

1. Create a query that excludes the items in L
1. Use the query to fetch X items from list (ordered as randomly as possible)
2. Add unique items to L
3. Repeat 1 - 3 until number of fetched items < X

Esto reduciría el número total de artículos devueltos de manera significativa, a costa de hacer más consultas.

No importa mucho si X es del todo exacto, pero la aleatoriedad es bastante importante. Esencialmente es probable que incluya las opciones más comunes de la primera consulta, por lo que la segunda consulta se excluyen estos y es probable que incluya las siguientes opciones más comunes y así sucesivamente a través de las iteraciones.

En el mejor de los casos, la primera consulta incluye todas las opciones, a continuación, la segunda consulta estará vacía. (X artículos recuperados en total, más de 2 consultas)

En el peor de los casos (por ejemplo, la consulta se clasifica por las opciones que estamos buscando, y hay más de X elementos con cada opción) vamos a hacer tantas consultas, ya que hay opciones. Volviendo aproximadamente X * X artículos en total.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top