0

当人们搜索我的网站时,我不想只搜索值 (q),我想用空格作为分隔符搜索每个单词。我已经编写了大部分代码,但有些部分我不知道该怎么做。

您可以检查下面代码中的“待办事项”并建议我一种方法吗?或者也许是一种完全不同的方法。顺便说一句,如果可能的话,我想保留 SQL 代码部分,因为这对我来说更自然,但所有 TODO 都可以在 LINQ 中完成。

谢谢

这是代码:

[HttpPost]
        public ActionResult Search(string q)
        {
            ViewBag.q = q;

            String[] strQueries = q.Split(' ');

            //TODO: Create an array of type var???

            foreach (string str in strQueries)
            {
                var recipesTemp = db.Recipes.SqlQuery(
                String.Format(
                "SELECT * FROM Recipe WHERE Name LIKE '%{0}%' " +
                "UNION ALL " +
                "SELECT * FROM Recipe WHERE IDRecipe IN ( " +
                "    SELECT IDRecipe FROM Subtitle WHERE Name LIKE '%{0}%') " +
                "UNION ALL  " +
                "SELECT * FROM Recipe WHERE IDRecipe IN ( " +
                "    SELECT IDRecipe FROM RecipeTag " +
                "        INNER JOIN Tag ON Tag.IDTag = RecipeTag.IDTag  " +
                "    WHERE Name LIKE '%{0}%') " +
                "UNION ALL   " +
                "SELECT * FROM Recipe WHERE IDRecipe IN ( " +
                "    SELECT IDRecipe FROM Subtitle " +
                "        INNER JOIN Ingredient ON Ingredient.IDSubtitle = Subtitle.IDSubtitle  " +
                "    WHERE QuantityAndName LIKE '%{0}%')", str)).Distinct().OrderBy(r => r.Name).ToList();

                //TODO: Add recipesTemp to the array of var
            }

            var recipes = //TODO: INTERSECT the results from all the recipesTemp in the array of type var

            return View("Search", recipes);
        }
4

3 回答 3

1

以下代码可以解决问题:

        var selectedRecipies = new List<IEnumerable<Recipy>>();

        foreach(...)
        {
            ...
            selectedRecipies.Add(recipesTemp);
        }

        var recipies = selectedRecipies.Aggregate((a, i) => a.Intersect(i));

此外,在你的地方,我也会考虑@KirkWoll 的评论并使用 FullTextSearch 而不是 LIKE。

于 2013-02-21T08:15:58.457 回答
0

对于其中的每一个strstrQueries您都在创建一个不同的格式化 SQL 查询,这些查询按名称排序并存储在List<T>where Tis a Recipe(?) 中。尝试这样的事情:

var allRecipes = strQueries.Select(str => db.Recipes.SqlQuery(
    String.Format(
        "SELECT * FROM Recipe WHERE Name LIKE '%{0}%' " +
        "UNION ALL " +
        "SELECT * FROM Recipe WHERE IDRecipe IN ( " +
        "    SELECT IDRecipe FROM Subtitle WHERE Name LIKE '%{0}%') " +
        "UNION ALL  " +
        "SELECT * FROM Recipe WHERE IDRecipe IN ( " +
        "    SELECT IDRecipe FROM RecipeTag " +
        "        INNER JOIN Tag ON Tag.IDTag = RecipeTag.IDTag  " +
        "    WHERE Name LIKE '%{0}%') " +
        "UNION ALL   " +
        "SELECT * FROM Recipe WHERE IDRecipe IN ( " +
        "    SELECT IDRecipe FROM Subtitle " +
        "        INNER JOIN Ingredient ON Ingredient.IDSubtitle = Subtitle.IDSubtitle  " +
        "    WHERE QuantityAndName LIKE '%{0}%')", str)).Distinct().OrderBy(recipe => recipe.Name))
    .SelectMany(recipe => recipe);

之后allRecipes应该是 type IEnumerable<Recipe>

于 2013-02-21T08:27:47.220 回答
0

试试这种方法,它会产生一条 SQL 语句:

var names = q.Split(' ');

if(names.Any())
{
    var firstName = names[0];

    var query = context.Recipes.Where (q => q.Name.Contains(firstName));
    // other unions ...
    // query = query.Union( context.Recipes.Where (...
    foreach (var name in names.Skip(1))
    {
        query = query.Union(context.Recipes.Where (q => q.Name.Contains(name)));
        // other unions ...
        // query = query.Union( context.Recipes.Where (...
    }

    // query evaluated now
    var recipes = query.ToList();
}
于 2013-02-21T09:32:44.283 回答