C# 基于一组关键字进行搜索
我需要根据一组关键字进行搜索,返回与这些关键字相关的所有广告。然后,结果是一个类别列表,其中包含每个类别的广告数量 在关键字搜索表中进行搜索:C# 基于一组关键字进行搜索,c#,asp.net-mvc,linq,entity-framework,C#,Asp.net Mvc,Linq,Entity Framework,我需要根据一组关键字进行搜索,返回与这些关键字相关的所有广告。然后,结果是一个类别列表,其中包含每个类别的广告数量 在关键字搜索表中进行搜索: public class KeywordSearch { public int Id { get; set; } public string Name { get; set; } public Keyword Keyword { get; set; } } 其中关键字表为: public class Keyword {
public class KeywordSearch
{
public int Id { get; set; }
public string Name { get; set; }
public Keyword Keyword { get; set; }
}
其中关键字表为:
public class Keyword
{
public int Id { get; set; }
public string Name { get; set; }
}
使用下表将广告与关键字关联:
public class KeywordAdCategory
{
[Key]
[Column("Keyword_Id", Order = 0)]
public int Keyword_Id { get; set; }
[Key]
[Column("Ad_Id", Order = 1)]
public int Ad_Id { get; set; }
[Key]
[Column("Category_Id", Order = 2)]
public int Category_Id { get; set; }
}
最后,类别表:
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
}
例如:
- 关键词:“梅赛德斯-奔驰”和“GLK”
- 关键词搜索:“梅赛德斯”和“奔驰”作为关键词“梅赛德斯-奔驰” 关键字“GLK”的“GLK”
- 类别:“轿车”和“卡车”
- 广告:汽车-奔驰GLK
卡车-奔驰Citan
如果我搜索“梅赛德斯-奔驰”,我会得到:
- 汽车:1辆
- 卡车:1辆
- 汽车:1辆
- 卡车:1辆
var keywordIds = from k in keywordSearchQuery
where splitKeywords.Contains(k.Name)
select k.Keyword.Id;
var matchingKac = from kac in keywordAdCategoryQuery
where keywordIds.Distinct().Contains(kac.Keyword_Id)
select kac;
var addIDs = from kac in matchingKac
group kac by kac.Ad_Id into d
where d.Count() == splitKeywords.Count()
select d.Key;
var groupedKac = from kac in keywordAdCategoryQuery
where addIDs.Contains(kac.Ad_Id) <--- EDIT2
group kac by new { kac.Category_Id, kac.Ad_Id };
var result = from grp in groupedKac
group grp by grp.Key.Category_Id into final
join c in categoryQuery on final.Key equals c.Id
select new CategoryGetAllBySearchDto
{
Id = final.Key,
Name = c.Name,
ListController = c.ListController,
ListAction = c.ListAction,
SearchCount = final.Count()
};
var keywordIds=来自关键字搜索查询中的k
其中splitKeywords.Contains(k.Name)
选择k.Keyword.Id;
var matchingKac=来自关键字ADCategoryQuery中的kac
其中keywordIds.Distinct()包含(kac.Keyword\u Id)
选择科航;
var addIDs=来自kac的匹配kac
按kac.Ad_Id将kac分为d组
其中d.Count()==splitKeywords.Count()
选择d键;
var groupedKac=来自关键字ADCategoryQuery中的kac
where addIDs.Contains(kac.Ad_Id)我还没有编译检查过这个或任何东西,所以它可能需要一些调整,但您正在寻找类似的东西
var matchingKac = keywordIds.Distinct().ToList()
.Aggregate(
keywordAdCategoryQuery.AsQueryable(),
(q, id) => q.Where(kac => kac.Keyword_Id == id));
你实际上是在说,“从关键字adCategoryQuery
开始,为每个关键字添加一个.Where()
条件说明其中必须包含该关键字。如果您发现聚合
难以阅读,您可以使用for
循环执行相同的操作。我想我现在有了一个解决方案。这是基于您的假设和一些假设:
关键词是完整的名称,如“梅赛德斯-奔驰GLK”、“梅赛德斯-奔驰Citan”
关键词搜索是“梅赛德斯”、“奔驰”和“GLK”表示“梅赛德斯-奔驰GLK”,以及“梅赛德斯”、“奔驰”和“奔驰Citan”表示“梅赛德斯-奔驰Citan”
“梅赛德斯-奔驰GLK”是“汽车”,“梅赛德斯-奔驰Citan”是“卡车”
考虑到这三个假设,我可以这么说
var keywordIds = from k in keywordSearchQuery
where splitKeywords.Contains(k.Name)
select k.Keyword.Id;
是罪魁祸首,下面的所有查询都依赖它。此查询将查找包含搜索字符串中任何单词的所有关键字
示例:给定的搜索字符串“Mercedes-Benz GLK”将分为“Mercedes”、“Benz”和“GLK”。您的查询现在会在“Mercedes-Benz GLK”和“Mercedes-Benz Citan”中找到“Mercedes”和“Benz”。
我认为很明显,你不想让“梅赛德斯-奔驰GLK”和“梅赛德斯-奔驰Citan”相提并论
解决方案是告诉查询将每个关键字与任何关键字搜索匹配,并返回适当的关键字:
var keywordIds = keywordSearchQuery
.GroupBy(k => k.Keyword.Id)
.Where(g => splitKeywords.All(w =>
g.Any(k => k.Name.Contains(w))))
.Select(g => g.Key);
至于addIds,将其更改为var addIds=matchingKac.Select(ad=>ad.ad_Id).Distinct();
应该可以。或者,如果addIds中只需要matchingKac,则可以将其更改为
var matchingKac = (from kac in keywordAdCategoryQuery
where keywordIds.Distinct().Contains(kac.Keyword_Id)
select kac.Ad_Id).Distinct();
并删除附加项。这可能不是直接的答案,但在这种“多参数搜索”情况下,我会忘记任何事情,只做简单的事情,例如:按汽车制造商、类别ID、MillageMax、价格进行搜索:
var searchResults = from c in carDb.Cars
where (c.Manufacturer.Contains(Manufacturer) || Manufacturer == null) &&
(c.CategoryId == CategoryId || CategoryId == null) &&
(c.Millage <= MillageMax || MillageMax== null) &&
(c.Price <= Price || Price == null)
select c
var searchResults=来自carDb.Cars中的c
其中(c.Manufacturer.Contains(Manufacturer)| | Manufacturer==null)&&
(c.CategoryId==CategoryId | | CategoryId==null)&&
(c.Millage如果你试图开发自己的搜索引擎,你可能会失败。为什么不试试Lucene呢。
这里有一个链接。
干杯我建议您添加正则表达式并省略该特殊字符,然后使用Linq
所以Mercedez Benz可以变成Mercedez和Benz,我建议不要用这种方式定义对象的关键字,因为你可能会搜索到太多的对象,或者什么也找不到。搜索时你总是会浪费你的时间。以用户关注的是查找而不是搜索的方式对对象进行分类。答复:
请随意回顾一下
下面是最重要的片段
与:
内部类搜索域
{
公共列表关键字{get;set;}
公共列表类别{get;set;}
公共列表关键字ADCategories{get;set;}
}
然后:
private static char[]关键字partssplitter=new char[]{'','-'};
StringInput的内部静态字典(字符串搜索短语、搜索域搜索域)
{
var identifiedKeywords=搜索短语
.拆分(关键字PartsSpliter);
var knownKeywordParts=已识别关键字
哪里
(ik=>
搜索域
.关键词
.SelectMany(x=>x.GetKeywordParts())
.Any(kp=>kp.Equals(ik、StringComparison.InvariantCultureIgnoreCase))
);
var关键字搜索=knownKeywordParts
.选择((kkp,n)=>新关键字搜索()
{
Id=n,
Name=kkp,
关键字=搜索域
.关键词
.单身
(k=>
k、 GetKeywordParts()
.Any(kp=>kp.Equals(kkp,StringComparison.InvariantCultureIgnoreCase))
)
});
var relevantKeywords=关键字搜索
.Select(ks=>ks.Keyword)
.Distinct();
var关键字adCategoriesByCategory=searchDomain.Categories
.GroupJoin
(
searchDomain.KeywordAdCategories,
c=>c.Id,
kac=>kac.Category_Id,
(c,kac)=>new{Category=c,AdKeywordsForCategory=kac}
);
var Relevant关键字分类=关键字分类按类别
哪里
(kacbk=>
相关关键词
全部的
(rk=>
卡布克
.AdKeywords类别
.Any(kac=>kac.Keyword_Id==rk.Id)
)
);
var FoundAdIncategories=相关关键字AdCate
internal class SearchDomain
{
public List<Keyword> Keywords { get; set; }
public List<Category> Categories { get; set; }
public List<KeywordAdCategory> KeywordAdCategories { get; set; }
}
private static char[] keywordPartsSplitter = new char[] { ' ', '-' };
internal static Dictionary<Category, Dictionary<int, List<KeywordAdCategory>>> FromStringInput(string searchPhrase, SearchDomain searchDomain)
{
var identifiedKeywords = searchPhrase
.Split(keywordPartsSplitter);
var knownKeywordParts = identifiedKeywords
.Where
(ik =>
searchDomain
.Keywords
.SelectMany(x => x.GetKeywordParts())
.Any(kp => kp.Equals(ik, StringComparison.InvariantCultureIgnoreCase))
);
var keywordkSearches = knownKeywordParts
.Select((kkp, n) => new KeywordSearch()
{
Id = n,
Name = kkp,
Keyword = searchDomain
.Keywords
.Single
(k =>
k.GetKeywordParts()
.Any(kp => kp.Equals(kkp, StringComparison.InvariantCultureIgnoreCase))
)
});
var relevantKeywords = keywordkSearches
.Select(ks => ks.Keyword)
.Distinct();
var keywordAdCategoriesByCategory = searchDomain.Categories
.GroupJoin
(
searchDomain.KeywordAdCategories,
c => c.Id,
kac => kac.Category_Id,
(c, kac) => new { Category = c, AdKeywordsForCategory = kac }
);
var relevantKeywordAdCategories = keywordAdCategoriesByCategory
.Where
(kacbk =>
relevantKeywords
.All
(rk =>
kacbk
.AdKeywordsForCategory
.Any(kac => kac.Keyword_Id == rk.Id)
)
);
var foundAdsInCategories = relevantKeywordAdCategories
.ToDictionary
(rkac =>
rkac.Category,
rkac => rkac.AdKeywordsForCategory
.GroupBy(g => g.Ad_Id)
.ToDictionary(x => x.Key, x => x.ToList())
);
return foundAdsInCategories;
}