Question

J'ai une liste de questions, chacune liée à une liste de balise.

Et les données suivantes:

Question1 : Tag1
Question2 : Tag1, Tag2
Question3 : Tag1, Tag2, Tag3
Question4 : Tag1, Tag3

Les critères suivants:

var tagsIds = new int[] { tag1, tag2 };

var res = session.CreateCriteria<Question>()
    .CreateCriteria( "Tags" )
    .Add( Restrictions.In( "id", tagsIds ) )
    .List<Question>();

renvoie (je comprends pourquoi, le "in" agit comme un OR)

Question1, Question2, Question3, Question4

Ou je voudrais obtenir seulement

Question2, Question3

comme ils ont tous deux balise1 ET tag2. J'y suis une façon de le faire?

Dans SQL, je ferais quelque chose comme:

SELECT *
FROM Question q
WHERE EXISTS (
    SELECT *
    FROM QuestionsToTags qtt
    WHERE qtt.Question_id = q.Id
    AND qtt.Tag_id IN ( 1, 2 )
    GROUP BY qtt.Question_id
    HAVING COUNT( qtt.Question_id ) >= 2 
)
Était-ce utile?

La solution 2

Utilisation hql:

var q = NHibernateSession.CreateQuery(
@"from Question question 
    where exists( 
        select q.id from Question q
        join q.Tags t
        where 
            t.id in (:ids)
            and q.id = question.id
        group by q.id
        having count(t.id)=:c_count )");

q.SetParameterList("ids", tagIds);
q.SetInt32("c_count", tagIds.Length);

Et en utilisant un ICriteria:

// here is the exists part
var dCriteria = DetachedCriteria.For<Question>("q")
    .SetProjection(Projections.GroupProperty(Projections.Id()))
    .Add(Restrictions.Eq(Projections.Count(Projections.Id()), tagIds.Length))
    // here we filter on the "parent" criteria
    .Add(Restrictions.EqProperty("q.id", "question.Id"))
    .CreateCriteria("Tags")
    .Add(Restrictions.In("id", tagIds));

var crit = NHibernateSession
    .CreateCriteria<Question>("question")
    .Add(Subqueries.Exists(dCriteria));

Autres conseils

Si vous avez seulement deux puis utilisez une restriction et

var res = session.CreateCriteria<Question>()
    .CreateCriteria( "Tags" )
    .Add( Restrictions.And(Restrictions.Eq("id", tag1), Restrictions.Eq("id", tag2))
    .List<Question>();

Si vous avez plus de deux ou un nombre inconnu puis utilisez Conjonction:

var conj = new Conjunction();
// use a loop to add all tags if number is unknown
conj.Add(Restrictions.Eq("id", tag1);
conj.Add(Restrictions.Eq("id", tag2);

var res = session.CreateCriteria<Question>()
    .CreateCriteria( "Tags" )
    .Add(conj)
    .List<Question>();

Il y a aussi une classe Disjunction à poignée multiples ou conditions.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top