asp.netsql-serverlinq-to-sqlsearch

Best Practices for Building a Search App?


I will be starting a simple datastore-and-search project soon. Basically, one of those "put my huge Excel spreadsheet into a database, build a web GUI for it, and make it searchable" type-things.

One thing that's been bugging me is the actual search logic that will be used when the user enters some criteria. I am imagining a search interface with a text field, and a few other filtering tools - drop down combo boxes and check boxes and such.

While that gives me very strong, granular control over the filtering I can perform, I am wondering what SO's thoughts are on actually performing the search. I'll be using ASP.NET, MS SQL Server, and Linq-To-SQL here, so keep those technologies in mind.

Off the top of my head, I think I'd do something like:

var results = from s in db.Stuff
              where (s.Prop1.Contains(textFilter) ||
                     s.Prop2.Contains(textFilter) ||
                     s.Prop3.Contains(textFilter)) &&
                     checkbox1.IsChecked ?
                          s.Prop4.ToLower().Equals(combobox1.Text) : true
              select s;

Here's what I know:

Here's what I'm asking:


Solution

  • I had to create a similar search for a comments system recently. What I did was I created some extension methods off of the comments which allowed me to pass in a generic filtering object.

    Here is the sample code that I used:

    This is just a partial method and does not have the return but it will give you a picture of what I am doing:

    public List<oComment> GetComments(oCommentSearch filters)
    {
    
        using (CommentDataContext db = CommentContextFactory.CreateContext())
        {
            var query = from comment in db.COMMENTs.FilterComments(filters)
                        select comment;
        }
    }
    

    As you can see off the COMMENTs i have FilterComments. This is an extension method. This method looks like this (this is the entire class I have):

    public static class CommentExtensions
        {
            public static IQueryable<COMMENT> FilterComments(this IQueryable<COMMENT> Comments, oCommentSearch Filters)
            {
                Filters = CheckFilter(Filters);
    
                IQueryable<COMMENT> tempResult = Comments;
    
                if(Filters.Classes.Count() > 0)
                {
                    tempResult = from t in tempResult
                                 where
                                     Filters.Classes.Contains(t.CLASS_ID)
                                 select t;
                }
    
                if (Filters.Flags.Count() > 0)
                {
                    tempResult = from t in tempResult
                                 where
                                     Filters.Flags.Contains((int) t.FLAG_ID)
                                 select t;
                }
    
                if (Filters.Types.Count() > 0)
                {
                    tempResult = from t in tempResult
                                 where
                                     Filters.Types.Contains(t.CommentTypeId)
                                 select t;
                }
                return tempResult;
            }
    
            private static oCommentSearch CheckFilter(oCommentSearch Filters)
            {
                Filters.Classes  = CheckIntArray(Filters.Classes);
                Filters.Flags =  CheckIntArray(Filters.Flags) ;
                Filters.Types =  CheckIntArray(Filters.Types) ;
                return Filters;
            }
    
            private static int[] CheckIntArray(int[] ArrayToCheck)
            {
                return ArrayToCheck == null || ArrayToCheck.Count() == 0 ? new int[] {} : ArrayToCheck;
            }
        }
    

    This should get you started in the right direction for what you are trying to do.

    Hope this helps!