Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 基于一组关键字进行搜索_C#_Asp.net Mvc_Linq_Entity Framework - Fatal编程技术网

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辆
    如果我搜索“梅赛德斯-奔驰GLK”,我会得到:

    • 汽车:1辆
    如果我搜索“Mercedes Citan”,我会得到:

    • 卡车: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;
    }