我有一个包含FirstName和LastName的表以及一个看起来像这样的查询:
var TheQuery = (from c in MyDC.Contacts
where (c.FirstName.Contains(TheSearchParameter) ||
c.LastName.Contains(TheSearchParameter))
select c.ColumnID).Distinct().ToList();
如果用户搜索John或Smith,则会返回记录,但如果用户搜索John Smith,则不会返回任何记录。 Contains()
如何工作以及我在查询中需要更改哪些内容才能按预期工作?
答案 0 :(得分:4)
不要开始使用and
,or
,StartsWith
,EndsWith
等组合,而是分析主要问题:
使用
的参数.Contains()
搜索查询合并两列
所以一般的答案是:
where Combine(table.Column1, table.Column2).Contains(TheSearchParameter)
问题在于Combine
函数是什么,并且没有一般答案。
在您的特定情况下,您希望搜索Name
列FirstName
和LastName
列的Name = "{FirstName} {LastName}"
。
即使这种组合通常没有定义(不同的语言有不同的名称规则),但假设您考虑到最常见的名称组合:
var TheQuery = (from c in MyDC.Contacts
where (c.FirstName + " " + c.LastName).Contains(TheSearchParameter)
select c.ColumnID).Distinct().ToList();
然后查询只是
NoReverseMatch at /
Reverse for 'thing_detail' with arguments '()' and keyword arguments '{u'slug': ''}' not found. 1 pattern(s) tried: ['things/(?P<slug>[-\\w]+)/$']
Request Method: GET
Request URL: http://localhost:8000/
Django Version: 1.8.4
Exception Type: NoReverseMatch
Exception Value:
Reverse for 'thing_detail' with arguments '()' and keyword arguments '{u'slug': ''}' not found. 1 pattern(s) tried: ['things/(?P<slug>[-\\w]+)/$']
Exception Location: /usr/local/lib/python2.7/dist-packages/django/core/urlresolvers.py in _reverse_with_prefix, line 496
Python Executable: /usr/bin/python
Python Version: 2.7.6
Python Path:
['/home/shashank/development/hellowebapp/hellowebapp',
'/usr/lib/python2.7',
'/usr/lib/python2.7/plat-x86_64-linux-gnu',
'/usr/lib/python2.7/lib-tk',
'/usr/lib/python2.7/lib-old',
'/usr/lib/python2.7/lib-dynload',
'/usr/local/lib/python2.7/dist-packages',
'/usr/lib/python2.7/dist-packages',
'/usr/lib/python2.7/dist-packages/PILcompat',
'/usr/lib/python2.7/dist-packages/gtk-2.0',
'/usr/lib/pymodules/python2.7',
'/usr/lib/python2.7/dist-packages/ubuntu-sso-client']
Server time: Sun, 13 Mar 2016 18:54:31 +0000
例如,如果联系 FirstName :“John”, LastName :“Smith”,上述查询将匹配“John”,“Smith”,“John Smith”但< em>“史密斯约翰”。
答案 1 :(得分:1)
您可以考虑在LINQ表达式中添加StartsWith
方法。 StartsWith的工作方式类似于SQL where Column LIKE 'Something%'
。您也可以添加EndsWith
以使搜索范围更广
var TheQuery = (from c in MyDC.Contacts
where (c.FirstName.Contains(TheSearchParameter) ||
c.FirstName.StartsWith(TheSearchParameter) ||
c.FirstName.EndsWith(TheSearchParameter) ||
c.LastName.StartsWith(TheSearchParameter) ||
c.LastName.EndsWith(TheSearchParameter) ||
c.LastName.Contains(TheSearchParameter))
select c.ColumnID).Distinct().ToList();
答案 2 :(得分:1)
var TheQuery = (from c in MyDC.Contacts
where ((c.FirstName.Contains(TheSearchParameter) &&
c.LastName.Contains(TheSearchParameter)) ||
(c.FirstName.Contains(TheSearchParameter) ||
c.LastName.Contains(TheSearchParameter)))
select c.ColumnID).Distinct().ToList();
使用( condition && condition ) ||
将强制括号内部为单个表达式,同时保留现有条件。
如果没有,请告诉我。希望这会有所帮助。
答案 3 :(得分:1)
我目前的理解是,您希望跨列搜索单词。虽然我确信我还没有完全理解我想要提出以下想法的要求。希望你能够将它变成一个完整的解决方案:
var words = searchQuery.Split(' ');
var query = (from c in MyDC.Contacts
select c);
//Force each word to occur.
foreach (var w in words)
query = query.Where(c => c.FN.Contains(w) || c.LN.Contains(w));
var TheQuery = (from c in query
select c.ColumnID).Distinct().ToList();
这引入了搜索所有单词的概念,而不是仅搜索一个字符串。
如果你想要名字和姓氏的单独逻辑,你可以有两个单词列表:一个用于FN,一个用于LN。
答案 4 :(得分:1)
我认为每个人都把简单的东西变得复杂。主要内容是获得与给定名称匹配的结果联系人。有两种情况, 你需要找到完全匹配。使用以下查询
var TheQuery = (from c in MyDC.Contacts
where (TheSearchParameter.Split(' ').Any(s => c.FirstName.Contains(s)) ||
TheSearchParameter.Split(' ').Any(s => c.LastName.Contains(s)))
select c.ColumnID).Distinct().ToList();
您需要找到所有相关的匹配
var TheQuery = (from c in MyDC.Contacts
where (c.FirstName + " " + c.LastName == TheSearchParameter)
select c.ColumnID).Distinct().ToList();
答案 5 :(得分:1)
你去(我更喜欢使用lambdas,但你不必):
var results = MyDC.Contacts
.Where(c => string.Join(" ",c.FirstName,c.LastName).Contains(TheSearchParameter))
.Select(c => c.ColumnId)
.Distinct()
.ToList();
通过将FirstName和LastName组合成一个字符串,您可以节省几个比较。
修改:更新了格式,因为单行难以理解。
答案 6 :(得分:1)
Contains
如何运作
假设您的FirstName
和LastName
属于string
类型,Contains
将检查字符串的任何子字符串是否与您的TheSearchParameter
匹配
因此,如果c.FirstName.Contains("John")
是以下任何一项,c.FirstName
将匹配:
John
vbJohn
John123
vbJohn123
虽然区分大小写,因此以下内容不匹配:
john
vbjohn
john123
vbjohn123
我需要在查询中更改它以使其按预期工作
假设您有以下名单:
John Bryant
John Bard
Smith Bard
John Smith
Ralla Smith
Smith John
Metajohn Rasmith
我假设您可能想要的最自然的“搜索”,即
TheSearchParameter
应该返回比“John Smith”更多的结果。)因此,通过输入“John”你想要返回:
John Bryant
John Bard
John Smith
Smith John
并将“史密斯”放入
Smith Bard
John Smith
Ralla Smith
Smith John
放“约翰史密斯”时
John Smith
Smith John
我建议你做的是使不区分大小写并按照以下方式检查:
string TheSearchParameter = "John Smith";
TheSearchParameter = TheSearchParameter.ToLower(); //case insensitive
string[] pars = TheSearchParameter.Split(new char[] {' '}, StringSplitOptions.RemoveEmptyEntries); //to get all the pars
var TheQuery = (from c in MyDC.Contacts
let l = new List<string>() {c.FirstName.ToLower(), c.LastName.ToLower()}
where l.Except(pars).Count() <= l.Count - pars.Length
select c.ColumnID).Distinct().ToList();
这里的关键是
where l.Except(pars).Count() <= l.Count - pars.Length
您可以通过它控制要考虑为匹配的匹配数。您在SearchParameter
中使用的字词越多,您预期会有更少的l.Except
(因为名称中的字词必须与搜索参数匹配)。
答案 7 :(得分:0)
美好的一天,请考虑我的方法
如果搜索全名,则上述两个答案都不会返回,因为他们只使用FirstName和LastName搜索
(例如: John.Contains(John Smith)= false
Smith.Contains(John Smith)= false
John.StartsWith(John Smith)= false
Smith.StartsWith(John Smith)= false
John.EndsWith(John Smith)= false
Smith.EndsWith(John Smith)= false
)
var TheQuery = (from c in x where ((TheSearchParameter.Contains(c.FirstName)
&& TheSearchParameter.Contains(c.LastName)) ||
((c.FirstName.Contains(TheSearchParameter) ||
c.LastName.Contains(TheSearchParameter))))
select c.ColumnId).Distinct().ToList();
TheSearchParameter.Contains(c.First / LastName)将考虑使用第一个AND姓的部分搜索TheSearchParameter的第一部分
第二部分将考虑使用TheSearchParameter
搜索第一个或最后一个名字如果你搜索约翰史密斯&#34;
并有约翰史密斯,约翰保罗和保罗史密斯的记录
第一部分将返回1个结果:John Smith 第二部分将返回0
如果您搜索&#34; John&#34;
第一部分将返回0结果 第二部分将回归:John Smith和John Paul
如果您搜索&#34; Smith&#34;
第一部分将返回0 第二部分将回归:约翰史密斯和保罗史密斯
谢谢!
答案 8 :(得分:0)
正如您所说,我们假设Collection包含FirstName为John
且LastName为Smith
的记录,还有另一条记录,其中FirstName =&#39; Sam&#39 ;和LastName为&#39; SmithX&#39;。 TheSearchParameter
将包含要搜索的字词。
现在让我们来看看您的查询将如何处理不同的输入。
案例1: TheSearchParameter =&#39; John&#39; - 将为您提供自c.FirstName.Contains(TheSearchParameter)
评估为true
以来的预期结果
案例2: TheSearchParameter =&#39; Smith&#39; - 将为您提供自c.LastName.Contains(TheSearchParameter)
评估为true
以来的预期结果
案例3: * TheSearchParameter =&#39; Jo&#39; *会为您提供自c.FirstName.Contains(TheSearchParameter)
评估为true
后的预期结果
到目前为止一切都很好;现在
案例4: TheSearchParameter =&#39; John Smith&#39; - 将为您提供空结果集由于没有包含{{1的FirstName或LastName但它是两者的结合。
在所有这些情况下,您可以采取哪些措施来获得正确的结果:
由于John Smith
可能包含firstName或LastName或Both,因此请在TheSearchParameter
中执行搜索操作。所以您的查询可能看起来像:
TheSearchParameter
现在,它为案例1-3 提供相同的结果并且将给出两个记录(&#34; John Smith&#34;和#34; Sam Smith&#34;即使姓氏是不同的。因为var TheQuery = (from c in MyDC.Contacts
where (TheSearchParameter.Contains(c.FirstName) ||
TheSearchParameter.Contains(c.LastName))
select c.ColumnID).Distinct().ToList();
评估为真;现在我们必须对此进行排序;
所以事实是
如果输入是FirstName和LastName的组合,我们必须确认组合应该从TheSearchParameter.Contains(c.LastName)
和EndsWith FirstName
开始。所以我建议你使用这样的搜索机制。以下代码段将帮助您完成此操作;
LastName
答案 9 :(得分:0)
如果我们假设名称由名字和姓氏组成 只是,你的数据中没有中间名。用户全名= 名字+姓氏。也许您可以尝试以下代码:
var TheQuery = (from c in MyDC.Contacts
where (c.FirstName + " " + c.LastName).Contains(TheSearchParameter)
select c.ColumnID).Distinct().ToList();
我们检查FirstName
中的LastName
和TheSearchParameter
:
var TheQuery = (from c in MyDC.Contacts
where (c.FirstName.Contains(TheSearchParameter) ||
c.LastName.Contains(TheSearchParameter) ||
TheSearchParameter.StartsWith(c.FirstName) ||
TheSearchParameter.EndsWith(c.LastName)
)
select c.ColumnID).Distinct().ToList();
例如:当Jhon或Smith进入时,Jhon Smith "Jhon Smith".StartsWith("Jhon")
或"Jhon
Smith".EndsWith("Smith")
是真的
Contacts
。 答案 10 :(得分:0)
string[] parametersArray = null;
int parametersCount = 0;
if(!string.IsNullOrEmpty(TheSearchParameter))
{
parametersArray = TheSearchParameter.Split(new char[0],StringSplitOptions.RemoveEmptyEntries);
parametersCount = parametersArray.Length;
}
var TheQuery = (from c in MyDC.Contacts
where (parametersCount == 0 || (parametersCount > 0 && (parametersArray.Contains(c.FirstName) ||
parametersArray.Contains(c.LastName))))
select c.ColumnID).Distinct().ToList();
答案 11 :(得分:0)
你试过这个吗?
var TheQuery = (from c in MyDC.Contacts
where (System.Threading.Thread.CurrentThread.CurrentCulture.CompareInfo.IndexOf(c.FirstName, TheSearchParameter, System.Globalization.CompareOptions.IgnoreCase) >= 0 ||
System.Threading.Thread.CurrentThread.CurrentCulture.CompareInfo.IndexOf(c.Lastname, TheSearchParameter, System.Globalization.CompareOptions.IgnoreCase) >= 0)
select c.ColumnID).Distinct().ToList();
答案 12 :(得分:-1)
我不太明白为什么你期望你的陈述有效。
string x = "abc" ;
string y = "abc def";
y.Contains(x); // returns true
x.Contains(y); // returns false