【问题标题】:Multiple keyword search using lambda [duplicate]使用 lambda 进行多个关键字搜索
【发布时间】:2014-06-11 05:57:45
【问题描述】:

我在这件事上卡了一天,进展甚微。

我希望能够按关键字以及其他静态变量过滤产品。这些关键字任何人都可以在搜索栏中键入。当有人输入多个关键字时,我遇到了困难。如果只有一个关键字,则查询效果很好。

如何搜索多个关键字都与一个项目相关,并且只返回与关键字匹配的项目?

示例关键字:帐篷、蓝色、徒步旅行

public static List<ProductObjectModel> GetProductsByKeyword(string keywords)
{
    using (TraegerEntities db = new TraegerEntities())
    {
        List<ProductObjectModel> lstObj = new List<ProductObjectModel>();

        if (!string.IsNullOrEmpty(keywords))
        {
            string[] keyword = keywords.Split(',');

            var lstAnon = (
                from r in db.Products
                join i in db.ProductImages on r.ProductId equals i.ProductId
                join c in db.ProductCategories on r.ProductId equals c.ProductId
                join cl in db.ProductCategoryList on c.ProductCategoryListId equals cl.ProductCategoryListId
                join k in db.ProductKeywords on r.ProductId equals k.ProductId
                join kl in db.ProductKeywordList on k.ProductKeywordListId equals kl.ProductKeywordListId
                where r.Archive == false
                where i.SmallImage == true
                where keyword.Any(kw => kl.Keyword.Contains(kw))
                group new
                {
                    Products = r,
                    ProductCategoryList = cl,
                    ProductImages = i,
                    ProductKeywordList = kl
                } by r.ProductId
            ).ToList();
        }

        foreach (var item in lstAnon.Skip(beginRange).Take(endRange))
        {
            ProductObjectModel obj = new ProductObjectModel();

            obj.ProductDetails = item.First().Products;
            obj.CategoryList = item.First().ProductCategoryList;
            obj.Images = item.First().ProductImages;
            obj.KeywordList = item.First().ProductKeywordList;

            lstObj.Add(obj);
        }

        return lstObj;
    }
}

【问题讨论】:

  • 你能申请 .Contains() 还是我相信这只是为了 linq-to-sql。
  • 我已经编辑了你的标题。请参阅“Should questions include “tags” in their titles?”,其中的共识是“不,他们不应该”。
  • JohnSaunders 我听你一遍又一遍地说,你应该编写一个自动插入此评论的用户脚本:)。
  • @JonH,他可能有一个,有一个插件可以让你指定自己的“自动”评论,所以只需点击两次即可发布:)
  • @JonH,在 .Any() where keyword.Any(kw =&gt; kl.Keyword.Contains(kw)) 我正在使用 .Contains。是不是因为我的关键字在一个数组中,所以它只找到第一个关键字?

标签: c# linq entity-framework lambda


【解决方案1】:

如果我理解正确的话,

当用户插入"Tent, Blue, Hiking"时,你想显示所有具有这三个关键字的项目吗?

如果是这种情况,从.Any().All 的简单交换应该会对您有所帮助。

像这样:where keyword.All(kw =&gt; kl.Keyword.IndexOf(kw, StringComparison.OrdinalIgnoreCase) &gt;= 0)

修剪你的东西:

var keyword = keywords.Split(',').Select(y => y.Trim());

【讨论】:

  • 没错,如果有人输入这三个关键字,我想找到与这三个匹配的所有产品。我已拆分字符串以创建关键字数组。我将 .Any() 更改为 .All(),现在返回 0 结果的一对多关键字。
  • 可能是字符大小写(如小写),也可能是空格。查看更新后的帖子。
  • 我尝试了一些变体。 var keyword = keywords.Split(',').Select(y =&gt; y.Trim()); 在数组末尾有一个空字符串。因此,我将数组更改为 string[] keyword = keywords.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries); 我还搞砸了 where 子句。仍然返回 0 个结果。感谢您对此的帮助。
  • 现在很难说有什么问题。我假设您尝试了 removeemptyentries + 使用 trim() 选择?
【解决方案2】:

在解决这个问题一周后,我终于找到了解决方案。通过比较两个列表,我能够得到我需要的结果。 This post 是我的解决方案。

public static List<ProductObjectModel> GetProductsByKeyword(string keywords)
{
    using (TraegerEntities db = new TraegerEntities())
    {
        List<ProductObjectModel> lstObj = new List<ProductObjectModel>();

        if (!string.IsNullOrEmpty(keywords))
        {
            string[] keyword = keywords.Split(',');

            List<ProductObjectModel> lstAnon  = (
                from r in db.Products
                join i in db.ProductImages on r.ProductId equals i.ProductId
                join c in db.ProductCategories on r.ProductId equals c.ProductId
                join cl in db.ProductCategoryList on c.ProductCategoryListId equals cl.ProductCategoryListId
                join k in db.ProductKeywords on r.ProductId equals k.ProductId
                join kl in db.ProductKeywordList on k.ProductKeywordListId equals kl.ProductKeywordListId
                where r.Archive == false
                where i.SmallImage == true
                select new ProductObjectModel
                {
                    Products = r,
                    CategoryList = cl,
                    KeywordList = kl,
                    Images = i
                }
            ).ToList();

            var lstFiltered = lstAnon;

            List<string> keywordList = new List<string>(keywords.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries));

            foreach (string word in keywordList)
            {
                var tempList = lstAnon.Where(r => r.KeywordList.Keyword == word).ToList();
                lstFiltered = lstFiltered.Intersect(tempList, new MyEqualityComparer()).ToList();
            }

            foreach (var item in lstAnon.Skip(beginRange).Take(endRange))
            {
                ProductObjectModel obj = new ProductObjectModel();

                obj.Products = item.Products;
                obj.CategoryList = item.ProductCategoryList;
                obj.Images = item.ProductImages;
                obj.KeywordList = item.ProductKeywordList;

                lstObj.Add(obj);
            }
        }

        return lstObj;
    }
}

public class MyEqualityComparer : IEqualityComparer<ProductObjectModel>
{
    public bool Equals(ProductObjectModel x, ProductObjectModel y)
    {
        return x.ProductObjectModel.ProductId == y.ProductObjectModel.ProductId;
    }

    public int GetHashCode(ProductObjectModelobj)
    {
        return obj.Products.ProductId.GetHashCode();
    }
}

【讨论】:

  • 您的解决方案是查询一切,然后在内存中过滤?这不是一个很好的解决方案。如果您的产品表有 90 亿行怎么办?
  • 对我们来说幸运的是,我们不会有 90 亿行。但你说得有道理。我想要一个更好的解决方案。
猜你喜欢
  • 1970-01-01
  • 2021-08-23
  • 1970-01-01
  • 1970-01-01
  • 2012-09-09
  • 2022-01-14
  • 2010-10-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多