收录日期:2020/10/31 20:59:08 时间:2010-09-07 03:26:51 标签:nhibernate

I have been searching the web for several hours to try to get an answer on this, but to no avail.

What I am trying to do is AND 'N' amount of Disjunctions to refine searches based on white space delimited query.

I have a 'Unity' which can be any combination of either a single person or organisation or multiple people/organisation, or any combination of the above.

So if I search for 'Smith' I want to match any companies OR people with the name 'Smith', easy.

However if someone were to type 'Smith w' and want matches on the different combos (OR on Person and Organisation).

So I would get a hit only for a Unity (combination of people and/or organisations) that has BOTH a company or person with smith AND either an organisation

 ICriteria query = Session.CreateCriteria(typeof(Unity), "u")
                .CreateCriteria("Organisations", "o", JoinType.LeftOuterJoin)
                .CreateCriteria("u.People", "p", JoinType.LeftOuterJoin)
                .SetResultTransformer(new DistinctRootEntityResultTransformer())
                .SetMaxResults(10);

        Disjunction keywordsCriteria = Restrictions.Disjunction();

        if (searchTerms.Contains(' ')) {
            foreach (var keyword in searchTerms.Split(' ')) {
                var term = string.Format("%{0}%", keyword);
                keywordsCriteria
                    .Add(Restrictions.Like("p.FirstName", term))
                    .Add(Restrictions.Like("p.LastName", term))
                    .Add(Restrictions.Like("o.Name", term));
            }

        }
        else
        {
            var term = string.Format("%{0}%", searchTerms);
            keywordsCriteria
                .Add(Restrictions.Like("p.FirstName", term))
                .Add(Restrictions.Like("p.LastName", term))
                .Add(Restrictions.Like("o.Name", term));
        }
        query.Add(keywordsCriteria);

        return query.List<Unity>();

This results in

where(p2_.Name1 like '%smith%' /* @p0 */
     or p2_.Name3 like '%smith%' /* @p1 */
     or o1_.EntityName like '%smith%' /* @p2 */
     or p2_.Name1 like '%w%' /* @p3 */
     or p2_.Name3 like '%w%' /* @p4 */
     or o1_.EntityName like '%w%' /* @p5 */)

However what I want to produce is the below

WHERE  ((p2_.Name1 like '%smith%' /* @p0 */
     or p2_.Name3 like '%smith%' /* @p1 */
     or o1_.EntityName like '%smith%' /* @p2 */)
     AND(
     p2_.Name1 like '%w%' /* @p3 */
     or p2_.Name3 like '%w%' /* @p4 */
     or o1_.EntityName like '%w%' /* @p5 */))

use this

if (!searchTerms.Contains(' '))
{
    Disjunction keywordsCriteria = Restrictions.Disjunction();
    var term = string.Format("%{0}%", searchTerms);
    keywordsCriteria
        .Add(Restrictions.Like("p.FirstName", term))
        .Add(Restrictions.Like("p.LastName", term))
        .Add(Restrictions.Like("o.Name", term));
    query.Add(keywordsCriteria);
}
else
{
    Conjunction conjunction = Restrictions.Conjunction();
    foreach (var keyword in searchTerms.Split(' '))
    {
        Disjunction disjunction = Restrictions.Disjunction();
        var term = string.Format("%{0}%", keyword);
            disjunction
            .Add(Restrictions.Like("p.FirstName", term))
            .Add(Restrictions.Like("p.LastName", term))
            .Add(Restrictions.Like("o.Name", term));
        conjunction.Add(disjunction);
    }
    query.Add(conjunction);
}

Thank you for the response, works a charm, just had to change one small bit, I had to create a new Disjunction for each loop or it would keep getting appended to.

I can't believe I didn't pick up on that!

if (searchTerms.Contains(' ')) {
            foreach (var keyword in searchTerms.Split(' ')) {
                var term = string.Format("%{0}%", keyword);
                Disjunction keywordsCriteria = Restrictions.Disjunction(); // <<--
                keywordsCriteria
                    .Add(Restrictions.Like("p.FirstName", term))
                    .Add(Restrictions.Like("p.LastName", term))
                    .Add(Restrictions.Like("o.Name", term));
                query.Add(keywordsCriteria);
            }
        }
        else
        {
            var term = string.Format("%{0}%", searchTerms);
            Disjunction keywordsCriteria = Restrictions.Disjunction(); // <<--
            keywordsCriteria
                .Add(Restrictions.Like("p.FirstName", term))
                .Add(Restrictions.Like("p.LastName", term))
                .Add(Restrictions.Like("o.Name", term));
            query.Add(keywordsCriteria);
        }