2013-06-12 130 views
3

我想建立一个接受多个关键字(空格分隔或逗号,这不是问题)的搜索。 我目前有这个多个关键字数据库搜索使用C#(LINQ到SQL)

public IQueryable<Post> Search(string criteria, int x) 
    { 
     return 
      (_db.Posts.Where(p => p.IsActive && 
       (p.PostText.Contains(criteria) || p.Weather.Contains(criteria) || p.Location.Contains(criteria)) 
      ).OrderByDescending(p => p.PostDate)).Take(x); 
    } 

但这只会返回完全匹配。我将如何搜索每个关键字并返回x个结果?顺便说它应该是一个OR。

感谢

回答

2

试试这个,我使用的并行性,以加快搜索。我正在检查字符串[]匹配中传递的任何键的一系列字符串。在我的例子中,我正在寻找“测试”和“1”,你会看到3个结果。

static void Main(string[] args) 
    {    
     List<string> list = new List<string>(); 
     list.Add("b lue number 1"); 
     list.Add("test number 234"); 
     list.Add("yello number 2334"); 
     list.Add("yes whippea number 324234"); 
     list.Add("test number asdf"); 

     var results = Program.Search(list,"test","1"); 

     Console.ReadLine(); 
    } 

要按照你的例子,你可以做这样的事情。

public List<Post> Search(string criteria, int x) 
    { 
     // Split all the search keys by space, so if you have "Search Word", you will get 
     // the occurances of [Search] and also [Word] 
     List<string> searchKeys = criteria.Split(' ').ToList<string>(); 

     // Filter active 
     _db = _db.Where(p => p.IsActive); 

     // Go through each key 
     foreach (string str in searchKeys) 
     { 
      _db = _db.Where(p => p.Location.Contains(str) 
        || p.PostText.Contains(str) 
        || p.Weather.Contains(str)); 
     } 

     // Return number wanted - and items will only be extracted here on the ToList() 
     return _db.OrderByDescending(p => p.PostDate).Take(x).ToList(); 
    } 

我正在循环条件并逐条添加条件。标准必须是您正在执行的搜索关键字的字符串,并在空格之间进行分隔以获得所有出现的位置。

+0

@Odle我更新了我的答案。 – Mez

+0

这是一个不好的方法来做到这一点,以及太多无关的东西。 .Any's不需要,因为这些属性都不是DbSets。对拆分进行foreach对性能不利,并且不能很好地转换为LINQ over EF,SQL或XML。 –

+0

此外,由于这是一个LINQ to SQL问题,您首先.Where.ToList将从数据库中检索所有记录,然后过滤它们而不是让SQL Server执行过滤服务器端。太多.ToLists()和.ToStrings()也是无用的,这些属性已经是字符串了。 –

0

如果你罚款一个需要精确匹配,那么这将工作关键字:

var allCriteria = criteria.Split(','); 

db.Posts.Where(p => allCriteria.Contains(p.PostText) || allCriteria.Contains(p.Weather) || allCriteria.Contains(p.Location) 
+0

当在其中一个属性中查找一个或多个碎片时,这不起作用。 –

+0

抱歉@Ek0nomik,那永远不会返回任何结果。例如,当我搜索“约克波士顿”时,它应该返回至少2个帖子(我知道它在那里),结果有位置“纽约”和“波士顿” – odle

-2
public IQueryable<Post> Search(string criteria, int x) 
{ 
    var allCriteria = criteria.Split(','); 

    var result=db.Posts.Where(p => 
     allCriteria.Any(c=>p.PostText.Contains(c)) 
     || allCriteria.Any(c=>p.Weather.Contains(c)) 
     || allCriteria.Any(c=>p.Location.Contains(c)) 
    ).Where(p=>p.IsActive) 
    .OrderByDescending(p => p.PostDate) 
    .Take(x); 
    return result; 
} 
+0

出现错误: System.NotSupportedException:本地序列不能用于除Contains运算符之外的查询运算符的LINQ to SQL实现。 – odle

+0

但是,当使用Linq-to-Entities时可以工作。 (至少EF 6.0) –

+0

这是一个有趣的错误。考虑到我们正在使用Contains运算符中的“Local sequence”。 –