left - nhibernate session createquery
Criterios de NHibernate selecciona elementos por grupo y suma de itemid dentro de otra tabla (2)
Ok, creo que encontré una solución.
Mi solución original según mi pregunta no funcionará porque NHibernate aún no admite la capacidad de hacer un grupo por propiedad sin agregarlo a la cláusula de selección (ver: texto del enlace ).
Sin embargo, mientras bromeaba, encontré estas cosas geniales llamadas ResultTransformers. Usando el transformador de resultados AliasToBean, Nhibernate mapeará automáticamente el alias que doy a cada elemento de proyección a las propiedades con el mismo nombre dentro del tipo que especifico. Simplemente especifiqué mi objeto SearchText (sin embargo, tuve que agregar una propiedad TotalSearchCount adicional para el elemento de proyección de suma). Pobló mis objetos perfectamente y los devolvió.
return Session.CreateCriteria(typeof(SearchTextLog))
.CreateAlias("SearchText", "st")
.SetProjection(Projections.ProjectionList()
.Add(Projections.Alias(Projections.GroupProperty("st.Id"), "Id"))
.Add(Projections.Alias(Projections.GroupProperty("st.Text"), "Text"))
.Add(Projections.Alias(Projections.Sum("SearchCount"), "TotalSearchCount")))
.SetMaxResults(topSearchLimit)
.AddOrder(Order.Desc("TotalSearchCount"))
.SetResultTransformer(Transformers.AliasToBean(typeof(SearchText)))
.List<SearchText>();
Me sorprende que esto no haya sido más fácil de hacer. Me tomó alrededor de 4 a 5 horas de investigación y desarrollo para resolver esto. Espero que mi experiencia en NHibernate sea más fácil con más y más experiencia.
¡Espero que esto ayude a alguien más allá!
public class SearchText
{
public virtual int Id { get; set; }
public virtual string Text { get; set; }
}
public class SearchTextLog
{
public virtual int Id { get; set; }
public virtual SearchText SearchText { get; set; }
public virtual User User { get; set; }
public virtual int SearchCount { get; set; }
public virtual DateTime LastSearchDate { get; set; }
}
Estoy tratando de seleccionar los 5 elementos principales de SearchText basados en la suma de su conteo dentro de SearchTextLog. Actualmente solo he podido resolver esto al realizar primero una consulta para obtener los 5 elementos principales y luego usar el resultado en una segunda consulta. Me preguntaba si alguien podría mostrarme la luz y enseñarme cómo podría integrar estas dos consultas separadas en una sola unidad.
Esto es lo que tengo actualmente:
var topSearchCriteria = Session.CreateCriteria(typeof (SearchTextLog))
.SetProjection(Projections.ProjectionList()
.Add(Projections.GroupProperty("SearchText.Id"))
.Add(Projections.Alias(Projections.Sum("SearchCount"), "SearchCount")))
.AddOrder(Order.Desc("SearchCount"))
.SetMaxResults(topSearchLimit)
.List<int>();
return Session.CreateCriteria<SearchText>()
.Add(Restrictions.In("Id", topSearchCriteria.ToArray()))
.List<SearchText>();
Editar:
Oh no, me acabo de dar cuenta de que mi solución actual perderá el orden importante por los resultados. Así que definitivamente tendré que incorporar las consultas. : - /
Editar:
Probé un mapeo bidireccional también para permitir la siguiente declaración, sin embargo, no puedo conseguir que devuelva los elementos de SearchText. Simplemente se queja de que las propiedades SearchText no están en una agrupación.
return Session.CreateCriteria<SearchText>()
.CreateAlias("SearchTextLogs", "stl")
.AddOrder(Order.Desc(Projections.Sum("stl.SearchCount")))
.SetMaxResults(topSearchLimit)
.SetResultTransformer(Transformers.AliasToEntityMap)
.List<SearchText>();
Disculpe mi ignorancia, pero Nhibernate es completamente nuevo para mí, y requiere una forma de pensar completamente diferente.
no funciona?
var critterRes = Session.CreateCriteria(typeof (SearchTextLog))
.SetProjection(Projections.ProjectionList()
.Add(Projections.GroupProperty("SearchText"))
.Add(Projections.Property("SearchText"))
.Add(Projections.Alias(Projections.Sum("SearchCount"), "SearchCount")))
.AddOrder(Order.Desc("SearchCount"))
.SetMaxResults(topSearchLimit)
.List<SearchText>()