简体   繁体   English

Linq 搜索多列多词搜索词

[英]Linq search multiple columns with multiple word search term

I am scratching my head how to achieve this我正在挠头如何实现这一目标

I have a table of products and variations.我有一张产品和变体表。

Let's say I have a record in my product table with name Sony Monitor假设我的产品表中有一条名为Sony Monitor的记录

In my variation table, I have a related variation with VariationName of 32"在我的变体表中,我有一个相关变体,其 VariationName 为32"

If I construct my linq as follows:如果我构造我的 linq 如下:

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

"Sony" would produce a search result. “Sony”会产生一个搜索结果。 32" would produce a search result. 32"将产生搜索结果。

Sony 32" would not produce a search result. Sony 32"不会产生搜索结果。

What is the best way to achieve this?实现这一目标的最佳方法是什么?

EDIT编辑

I have created a ViewModel (ProductSearch) for my search results for ease of use.为了便于使用,我为我的搜索结果创建了一个 ViewModel (ProductSearch)。 I added "Matches" as an integer field.我将“匹配”添加为 integer 字段。

I Concat my product and variation table to get a list of results.我连接我的产品和变体表以获取结果列表。 The code I am having problems with is as follows:我遇到问题的代码如下:

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();

The error I am receiving is:我收到的错误是:

The LINQ expression 'x' could not be translated.无法翻译 LINQ 表达式“x”。 Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'.以可翻译的形式重写查询,或通过插入对“AsEnumerable”、“AsAsyncEnumerable”、“ToList”或“ToListAsync”的调用显式切换到客户端评估。

Steve,史蒂夫,

I think the answer depends, to some extent, on where your data resides.我认为答案在某种程度上取决于您的数据所在的位置。 Generally,一般来说,

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

Should work.应该管用。 If you're using something like LINQ to SQL, or LINQ to Entities, things may start to get a bit messy as some of those technologies don't support string.contains如果您使用 LINQ 到 SQL 或 LINQ 到实体,事情可能会开始变得有点混乱,因为其中一些技术不支持string.contains

In the end, you may end up having to do something like:最后,您可能最终不得不执行以下操作:

var productSearch = products.Where(p => searchTerm.Any(x => p.Name.Contains(searchTerm)) || 
    searchTerm.Any(z => p.Variation.Name.Contains(searchTerm)));

Simple.简单的。 Try this:尝试这个:

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();

That tries to find as many matches as possible between the search terms and the elements you're searching, giving you the most matches first and down to having at least one match.这会尝试在搜索词和您正在搜索的元素之间找到尽可能多的匹配项,首先为您提供最多的匹配项,然后至少有一个匹配项。

You may want to add some .ToLowerInvariant() calls to allow a case-insensitive search.您可能需要添加一些.ToLowerInvariant()调用以允许不区分大小写的搜索。


Try this variation to get the data to load into memory first.尝试此变体以首先将数据加载到 memory 中。

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();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM