首页 > 解决方案 > Linq用多个词搜索词搜索多列

问题描述

我正在挠头如何实现这一目标

我有一张产品和变体表。

假设我的产品表中有一条名为Sony Monitor的记录

在我的变体表中,我有一个相关变体,其 VariationName 为32"

如果我按如下方式构建我的 linq:

var productSearch = products.Where(p => p.Name.Contains(searchTerm) || p.Variation.Name.Contains(searchTerm)

“Sony”会产生一个搜索结果。32"将产生搜索结果。

Sony 32"不会产生搜索结果。

实现这一目标的最佳方法是什么?

编辑

为了便于使用,我为我的搜索结果创建了一个 ViewModel (ProductSearch)。我将“匹配”添加为整数字段。

我连接我的产品和变体表以获取结果列表。我遇到问题的代码如下:

string searchTerm = "Sony 32";
            string[] searchTerms = searchTerm.Split(' ');
            //Concat my two queries (this works fine without the new search code)
            var productSearch = rootProducts.Concat(variableProducts)
                .OrderBy(p => p.Name)
                .Select(p => new ProductSearch()
                {
                    InternalSku = (string)p.InternalSku,
                    ProductId = (int)p.ProductId,
                    ProductVariationId = (int?)p.ProductVariationId,
                    Name = (string)p.Name,
                    ManufacturerSku = (string)p.ManufacturerSku,
                    Ean = (string)p.Ean,
                    ImageUrl = p.ImageUrl,
                    WebDisplay = (bool)p.WebDisplay,
                    VariationName = (string)(p.Name),
                    Matches =
            new[] { p.Name, p.VariationName }
                .SelectMany(x => searchTerms, (x, y) => x.Contains(y))
                .Count(),
                })
                .Skip(skip)
                .Take(take)
                .ToList();

我收到的错误是:

无法翻译 LINQ 表达式“x”。以可翻译的形式重写查询,或通过插入对“AsEnumerable”、“AsAsyncEnumerable”、“ToList”或“ToListAsync”的调用显式切换到客户端评估。

标签: c#sqllinq

解决方案


简单的。尝试这个:

var searchText = "Sony 32";
var searchTerms = searchText.Split(' ');

var productSearch =
    products
        .Select(p => new
        {
            product = p,
            matches =
                new[] { p.Name, p.Variation.Name }
                    .SelectMany(x => searchTerms, (x, y) => x.Contains(y))
                    .Count(),
        })
        .Where(x => x.matches >= 1)
        .OrderByDescending(x => x.matches)
        .Select(x => x.product)
        .ToArray();

这会尝试在搜索词和您正在搜索的元素之间找到尽可能多的匹配项,首先为您提供最多的匹配项,然后至少有一个匹配项。

您可能需要添加一些.ToLowerInvariant()调用以允许不区分大小写的搜索。


尝试此变体以首先将数据加载到内存中。

var productSearch =
    products
        .Select(p => new { p.Name, Variation = p.Variation.Name })
        .ToArray()
        .Select(p => new
        {
            product = p,
            matches =
                new[] { p.Name, p.Variation }
                    .SelectMany(x => searchTerms, (x, y) => x.Contains(y))
                    .Count(),
        })
        .Where(x => x.matches >= 1)
        .OrderByDescending(x => x.matches)
        .Select(x => x.product)
        .ToArray();

推荐阅读