SharePoint 2010: Utilizando el Servicio de Metadatos para clasificación de Personas

diciembre 5, 2010
By

taxonomyUna persona generalmente desempeña más de un rol en una organización. Por ejemplo, el “Asistente de Dirección” en una empresa es un “Trabajador” que a su vez es un “Directivo” y puede que sea también el “Presidente del Club de Fans del equipo Industriales” en el caso del beisbol Cubano. Como podrá notar estos roles comparten una jerarquía (Por ejemplo “Trabajador” > “Directivo” > “Asistente de Dirección”). En este artículo veremos cómo utilizar la nueva característica de SharePoint 2010 conocida como Servicio de Metadatos Administrados (Managed Metadata Service) para modelar de manera eficiente los roles en una organización.

Antecedentes

En SharePoint 2007 una solución a este problema hubiese sido crear una lista de personal con una columna “Rol” de tipo Selección (Choice) multivaluada que especifique los roles a asignar. El problema de esta solución es que no permite definir la relación jerárquica entre los roles. Y pudiera pensarse que esta relación entre roles no es muy importante, pero realmente sí lo es. Por ejemplo, supongamos que queremos responder preguntas al estilo de “¿Cuantos trabajadores existen en la organización?” o “’¿Con cuantos directivos cuenta la organización?”. Si al introducir los datos en la lista de personal, se selecciona únicamente el rol “Asistente de Dirección” para un usuario, a la vista de SharePoint este usuario no sería trabajador de la organización. Entonces con este modelo el usuario que rellena la lista de personal tendría que obligatoriamente llevar mentalmente la jerarquía y marcar manualmente que el “Asistente de Dirección” es a su vez “Directivo” y “Trabajador”. El lector comprenderá que sería impracticable recordar mentalmente la jerarquía organizativa de una empresa real (generalmente los organigramas son bastante extensos).

Hay un artículo en inglés titulado “La muerte del campo Selección en SharePoint 2010” (The Death of the Choice Field in SharePoint 2010) [http://www.sharepointanalysthq.com/2010/07/the-death-of-the-choice-field-in-sharepoint-2010/] que muestra la evolución del Choice Field en el Managed Metadata Field que viene con SharePoint 2010 así como las ventajas y desventajas que este último tiene. Como podrá observar a lo largo de este artículo, tiene mucho sentido hablar de “La Muerte del Choice” Sonrisa

Managed Metadata Service

Los metadatos administrados se definen como una colección jerárquica de términos administrados centralmente que pueden ser utilizados como atributos en elementos de SharePoint 2010. En otras palabras, podemos crear una jerarquía de Etiquetas que luego podemos asignar a Páginas, Elementos de Listas, Bibliotecas de Documentos, Sitios y de manera general cualquier elemento que herede de Item en SharePoint 2010. Existe una API para su gestión que incluye las características deseables en un sistema de taxonomías tales como sumario automático y términos multi-lingues. Además SharePoint 2010 de manera predeterminada cuenta con unos WebParts tales como la “Nube de Términos” (Tag Cloud) que son imprescindibles en el trabajo con taxonomías en la Web 2.0.

Paso 1: Creando la taxonomía

Primeramente debemos conectarnos al servicio de metadatos de SharePoint. Para ello abrimos una sesión utilizando la clase TaxonomySession y luego nos conectamos a un almacén de términos personalizado (o de manera predeterminada utilizados el almacén “Managed Metadata Service”).

// Iniciando una nueva sesión (TaxonomySession) para el sitio actual.
TaxonomySession session = new TaxonomySession(site);

// Instanciar "Managed Metadata Service" para la sesión actual.
TermStore termStore = session.TermStores["Managed Metadata Service"];

Una vez obtenido el almacén de términos, podemos crear la jerarquía:

Group myOrg = termStore.CreateGroup("Mi Organización");
TermSet myRoles = myOrg.CreateTermSet("Roles", 3082);
Term employee = myRoles.CreateTerm("Trabajador", 3082);
Term executive = employee.CreateTerm("Directivo", 3082);
Term assistant = executive.CreateTerm("Asistente de Dirección", 3082);
Term ceo = executive.CreateTerm("Director", 3082);
termStore.CommitAll();

Note que estamos utilizando el LCID 3082 que es Español España (es-ES). De manera predeterminada se utiliza Inglés Estados Unidos que es el 1033.

Paso 2: Creando columna de Roles

Ya tenemos definida la taxonomía que representa los roles de la organización. Ahora toca modelar la lista de personal. Para ello hay dos acercamientos:

  1. Utilizar el User Information List de la colección de sitios
  2. Crear una lista personalizada

Como sabrán el User Information List es una lista que existe en cada colección de sitios y que contiene un elemento que representa a cada usuario que accede a la colección de sitios (o si de manera programática se utiliza la API SPWeb.EnsureUser). Esta es una lista especial en SharePoint que tiene otras funcionalidades como la sincronización con los perfiles de usuarios, pero en principio, es una lista a la que se le pueden añadir columnas personalizadas.

Alrededor del User Information List se han creados muchos mitos, leyendas y miedos  (que en algunos casos son reales) debido a que SharePoint almacena esta lista internamente de manera “especial”. Si usted es como un compañero de trabajo mío que le aterra la idea de modificar el User Information List pues utilice el segundo acercamiento que en principio es similar.

El segundo acercamiento básicamente consiste en crear una lista que contenga un campo de tipo Persona que mapee el ID del Usuario (que es muy similar a lo que hace el User Information List).

En cualquier caso, el código que les presento a continuación funciona tanto para el User Information List como para cualquier otra lista; basta con cambiar la primera línea de código.

// Obteniendo User Information List
SPList list = site.RootWeb.SiteUserInfoList;

// Creando columna "Roles"
list.ParentWeb.AllowUnsafeUpdates = true;
var tagsField = list.Fields
    .CreateNewField("TaxonomyFieldType", "Roles") as TaxonomyField;
//AllowMultiplevalues: Verdadero si se permite tener más de un tag
tagsField.AllowMultipleValues = false;
//AnchorId: Permitir solo Etiquetas que hereden del GUID especificado.
tagsField.AnchorId = Guid.Empty;
//Open: Verdadero si se permite definir manualmente nuevas Etiquetas.
tagsField.Open = false;
//SspId: Id del TermStore
tagsField.SspId = myRoles.TermStore.Id;
//AnchorId: Limita los posibles términos a añadir al TermSet creado
tagsField.TermSetId = myRoles.Id;
list.Fields.Add(tagsField);
list.Update();
list.ParentWeb.AllowUnsafeUpdates = false;

Como podrá observar es bastante estándar la manera de añadir una nueva columna a una lista. Lo nuevo aquí es que se utiliza el tipo TaxonomyFieldType como tipo y para el manejo del campo pues se utiliza TaxonomyField (Me pregunto por qué no le pusieron SPFieldTaxonomy para seguir con la filosofía de nombres para campos en SharePoint). Este nuevo tipo de campo de taxonomías está basado en el tipo estándar de Búsqueda (SPFieldLookup) que existe en SharePoint. De hecho, cada término de este sistema de términos tiene asociado un ID que es el que se almacena en este campo así que no existe mística alguna en cuanto al almacenamiento de las etiquetas en la lista. Lo novedoso ocurre a la hora de convertir un término en un ID. Esto lo veremos posteriormente en este artículo.

Paso 3: Etiquetando los elementos de la lista programáticamente

Hasta ahora tenemos una lista (que puede ser el User Information List) que contiene una columna “Roles” de tipo TaxonomyField. Veamos cómo etiquetar un elemento de dicha lista.

public static void SetManagedMetadataField(TaxonomySession oSession, SPListItem oItem, Guid gTermID, string sFieldName)
{
    TaxonomyField oField = (TaxonomyField)oItem.Fields[sFieldName];
    Term oTerm = oSession.GetTerm(gTermID);
    oField.SetFieldValue(oItem, oTerm);
}

El método anterior recibe como parámetros una sesión, un GUID que identifica al término que se desea asignar, un elemento de lista y finalmente el nombre de la columna donde se almacenan las etiquetas. Note que este método reemplaza cualquier etiqueta que se haya asignado al elemento. Si se quisiera asignar más de una etiqueta, primero habría que poner en verdadero el valor de la propiedad AllowMultipleValues en la definición del campo y luego utilizar la clase TaxonomyFieldValueCollection para gestionar múltiples etiquetas.

Siguiendo el hilo conductor de nuestro artículo, utilizaríamos este método de la siguiente manera:

// Obteniendo Elemento que representa al Usuario
SPUser user = site.RootWeb.EnsureUser("DOMINIO\\usuario");
SPListItem userItem = list.GetItemById(user.ID);
// Asociando el tag assistant.id que sería "Asistente de Dirección"
SetManagedMetadataField(session, userItem, assistant.Id, "Roles");

Paso 4: Consultando elementos que estén marcados con cierta etiqueta

Veamos ahora como realizar una de las preguntas que comentábamos al principio: “¿Cuantos trabajadores existen en la organización?”. Para ello vamos a suponer que en ningún caso se ha etiquetado directamente algún elemento con la etiqueta “Trabajador”.

Como el campo “Roles” que creamos anteriormente es un heredero del tipo SPFieldLookup pues consultar este tipo de campo no es novedad y lo podemos hacer mediante una consulta CAML. Lo significativo consiste en cómo utilizar la jerarquía de etiquetas (taxonomía) para preguntar por los elementos que estén etiquetados directamente con “Trabajador” o con cualquier etiqueta que herede de “Trabajador”:

// Obtener los IDs correspondientes a un término y sus descendientes
int[] wssIds = TaxonomyField.GetWssIdsOfTerm(site,
    term1.TermStore.Id,  // ID TermStore
    term1.TermSet.Id,    // ID TermSet
    term1.Id,            // ID Term
    true,                // Incluír descendientes
    500);                // Límite                       

// Creando consulta CAML
var values = new StringBuilder();
foreach(var id in wssIds)
    values.AppendFormat("<Value Type=\"Integer\">{0}</Value>",id);

var query = new SPQuery {
    Query =
        string.Format(
        "<Query>" +
        " <Where>" +
        "  <In>" +
        "   <FieldRef LookupId=\"TRUE\" Name=\"Grupo\" />" +
        "   <Values>" +
        "       {0}" +
        "   </Values>" +
        "  </In>" +
        " </Where>" +
        "</Query>",
        values.ToString())
};

foreach (SPListItem item in list.GetItems(query))
{
    Console.WriteLine(item.Title);
}

Como se puede observar en el código la API TaxonomyField.GetWssIdsOfTerm es quien viene a salvar el día en este caso. A este método se le pasa un almacén de términos, un conjunto de términos y el término en particular que se quiere obtener seguido de un booleano que determina si se incluyen los herederos y un límite de elementos. El resultado sería el listado de ID que hay que buscar en el campo de etiquetas que como hemos visto hasta ahora es de tipo búsqueda. La idea consiste en construir una consulta CAML que devuelva sólo (where) los elementos que contengan (in) alguno de los valores (values) devueltos por el método GetWssIdsOfTerm.

Conclusiones

El servicio de metadatos administrado, es una potente herramienta que no solo es útil para “etiquetar” de manera clásica los elementos de SharePoint (etiquetado al que estamos acostumbrados en la Web 2.0) sino que permite modelar situaciones/problemas como el que presentamos en este artículo. Solo la imaginación será el límite de este servicio de metadatos administrados.

Artículos relacionados

A Brief Introduction to Enterprise Metadata Management for Microsoft SharePoint Server 2010 Developers

http://msdn.microsoft.com/en-us/library/ee832800.aspx

Metadata and Taxonomy Programming Model

http://msdn.microsoft.com/en-us/library/ee556337.aspx

Querying on Managed Metadata Field Values

msdn.microsoft.com/en-us/library/ff625182.aspx

TaxonomyField Class

http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.taxonomy.taxonomyfield.aspx

How to create Managed Metadata column in SharePoint 2010

http://www.c-sharpcorner.com/UploadFile/anavijai/4349/Default.aspx

Tags:

3 Responses to SharePoint 2010: Utilizando el Servicio de Metadatos para clasificación de Personas

  1. Lester Sánchez
    Lester Sánchez on diciembre 5, 2010 at 9:48 pm

    La introducción de los servicios para la gestión de metadatos en SharePoint 2010 fue una de las mejoras más significativas. Es cierto que muchas cosas que antes solo podían hacerse con campos de tipo Choice ahora tienen la alternativa de representarse como etiquetas de una taxonomía. Sin embargo, los campos choice siguen valiendo para casos simples y más “locales”. Por otra parte, no estoy seguro si tenemos taxonomías en WSS. En ese caso los campos choice siguen siendo la única opción en WSS. Larga vida a los campos choice, vivan las taxonomías ;-)

  2. Abel García on diciembre 6, 2010 at 3:27 pm

    Creo q conozco a “tu colega” al q no le hacen mucha gracia las modificaciones del UIL ;-) . En este caso particular me luce como una buena idea la creación de un nuevo campo en la UIL puesto q todo el mundo tendra al menos un rol en la organizacion, en este caso, “Trabajador”. Pero pienso q vale resaltar q no siempre es una buena idea poner metadatos sobre los usuarios directamente en la UIL por 2 razones fundamentales:

    La UIL esta disponible para todos los sitios de la colección de sitios, algunos metadatos pueden no ser relavantes en todos estos sitios.
    En algunos casos los metadatos que necesitamos solo son concernientes a un subconjunto de los usuarios, por ejemplo, “Número de Votos en Juntas”. Esta información solamente tiene sentido para los usuarios que son directivos de la empresa, por lo q me parece q no vale la pena hacer cargar a todos los usuarios con este campo cdo la mayoría lo tendrán vacío.

    No obstante creo q “tu colega” encontrará este artículo muy interesante y para su problema particular este pudiera ser un muy buen punto de partida.

Deja un comentario

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

*

Acerca del autor...

Alejandro Tamayo

Web: http://www.linkedin.com/in/atamayocastillo
Alejandro Tamayo
Professor, Researcher, Developer, Consultant and technology enthusiast. Master of Science (MSc) in Computer Science and member of Weboo Research Group.Leer completo