How to use Full Text Search for any property with QueryOver API
Asked Answered
D

1

6

I'm trying to use the SQL function CONSTAINS to filter some data on QueryOver API.

The main issue is i can't use SqlFunction in where clause, it does not compile, because a ICriterion is needed.

var result = Session.QueryOver<Individual>()
    .Where(Projections.SqlFunction(
        "FullTextContains", NHibernateUtil.Boolean,
        Projections.Property<Individual>(x => x.LastName),
        Projections.Constant("something")))
        .List();

I tried to match it to a TRUE constant, but when the query is executed it generates syntax error, because CONSTAINS function can't be used with equals operator.

var result = Session.QueryOver<Individual>()
    .Where(Restrictions.Eq(Projections.SqlFunction(
        "FullTextContains", NHibernateUtil.Boolean,
        Projections.Property<Individual>(p => p.LastName),
        Projections.Constant("something")), true))
        .List();

How can i use a boolean sql function directly in where expression on QueryOver API?

Deprecate answered 31/7, 2015 at 0:1 Comment(0)
D
6

This is my finding for letting QueryOver support it:

var projection = Projections.SqlFunction("FullTextContains", 
    NHibernateUtil.Boolean, 
    Projections.Property<Individual>(x => x.LastName),
    Projections.Constant("something"));

var result = Session.QueryOver<Individual>()
    .Where(new ProjectionAsCriterion(projection))
    .List();

To use a IProjection as a ICriterion I created my own implementation based on SimpleExpression class from NHibernate project.

public class ProjectionAsCriterion : AbstractCriterion
{
    private readonly IProjection _projection;

    public ProjectionAsCriterion(IProjection projection)
    {
        _projection = projection;
    }

    public override SqlString ToSqlString(ICriteria criteria, ICriteriaQuery criteriaQuery,
        IDictionary<string, IFilter> enabledFilters)
    {
        var columnNames = CriterionUtil.GetColumnNamesForSimpleExpression(
            null, _projection, criteriaQuery, criteria, enabledFilters, this, string.Empty);

        var sqlBuilder = new SqlStringBuilder(4 * columnNames.Length);

        for (int i = 0; i < columnNames.Length; i++)
        {
            if (i > 0)
            {
                sqlBuilder.Add(" and ");
            }

            sqlBuilder.Add(columnNames[i]);
        }
        return sqlBuilder.ToSqlString();
    }

    public override TypedValue[] GetTypedValues(ICriteria criteria, ICriteriaQuery criteriaQuery)
    {
        var typedValues = new List<TypedValue>();

        if (_projection != null)
        {
            typedValues.AddRange(_projection.GetTypedValues(criteria, criteriaQuery));
        }
        typedValues.Add(GetParameterTypedValue(criteria, criteriaQuery));

        return typedValues.ToArray();
    }

    private TypedValue GetParameterTypedValue(ICriteria criteria, ICriteriaQuery criteriaQuery)
    {
        return CriterionUtil.GetTypedValues(criteriaQuery, criteria, _projection, null).Single();
    }

    public override IProjection[] GetProjections()
    {
        return new[] { _projection };
    }

    public override string ToString()
    {
        return _projection.ToString();
    }
}
Deprecate answered 8/10, 2015 at 23:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.