Question

I'm using this search function. but I need it to do an "and" not an "or" I cant seem to get it to return the results I want. I need to perform a search function where the search results match the text entered in box. But only a partial search. For example if I type in "Super D" I want it to find everything that contains a "Super" AND a "D".

public static class ObjectContextExtensions {

    public static IQueryable<T> FullTextSearch<T>(this IQueryable<T> queryable, string searchKey)
    {
        return FullTextSearch<T>(queryable, searchKey, false);
    }

    public static IQueryable<T> FullTextSearch<T>(this IQueryable<T> queryable, string searchKey,
                                                  bool exactMatch)
    {

        ParameterExpression parameter = Expression.Parameter(typeof(T), "c");
        MethodInfo containsMethod = typeof(string).GetMethod("Contains", new Type[] { typeof(string) });
        // MethodInfo toStringMethod = typeof (object).GetMethod("ToString", new Type[] {});


        var publicProperties =
            typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)
                      .Where(p => p.PropertyType == typeof(string));
        Expression orExpressions = null;
        string[] searchKeyParts;

        if (searchKey == null)
        {
            searchKey = "0";
        }
        searchKeyParts = !exactMatch ? searchKey.Split(' ') : new[] { searchKey };


        foreach (MethodCallExpression callContainsMethod in from property in publicProperties 
         select Expression.Property(parameter, property) into nameProperty 
         from searchKeyPart in searchKeyParts 

        let searchKeyExpression = Expression.Constant(searchKeyPart) let containsParamConverted = Expression.Convert(searchKeyExpression, typeof(string)) 

         select Expression.Call(nameProperty, containsMethod, (Expression)containsParamConverted))
        {
            if (orExpressions == null)
            {
                orExpressions = callContainsMethod;
            }
            else
            {
                orExpressions = Expression.Or(orExpressions,callContainsMethod);
            }
        }


        MethodCallExpression whereCallExpression = Expression.Call(
            typeof(Queryable),
            "Where",
            new Type[] { queryable.ElementType },
            queryable.Expression,
            Expression.Lambda<Func<T, bool>>(orExpressions, new ParameterExpression[] { parameter }));

        return queryable.Provider.CreateQuery<T>(whereCallExpression);
    }

}
Was it helpful?

Solution

Looks as though setting exactMatch to true would do the trick as it wouldn't split the search terms up.

FullTextSearch<MyType>(searchKey, true)

Failing that, change

orExpressions = Expression.Or(orExpressions,callContainsMethod);

to

andExpressions = Expression.And(andExpressions,callContainsMethod);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top