感谢您的光临。
我有一个C#方法,允许用户传入搜索和过滤器对象。然后,该方法通过实体框架将FULLTEXT
函数作为IQueryable
调用。然后根据过滤器的约束进一步突变相同的IQueryable
并最终枚举。这很好用,这是一个伪代码示例:
var db = MyDataContext();
IQueryable<Foo> results = db.QueryAllMyFoos();
results = db.SomeFullTextFunctionInTheDatabase("buzz");
. . .
return results.Skip(0).Take(10); //etc. etc.
我被要求必须保存搜索并在结果集中启用搜索。
我认为通过存储表示第一次搜索的唯一ID的整数数组,然后使用.Contains()
(再次,伪代码)将它们传递到第二次搜索的谓词中,可以轻松解决这个问题:
var firstSearchResults = int[]{50,63,123. . . .456788};
IQueryable<Foo> results = db.QueryAllMyFoos();
results = db.SomeFullTextFunctionInTheDatabase("fizz").Where(w => firstSearchResults.Contains(w.Id));
嗯,它有效但是考虑到firstSearchResults
通常可能包含超过20,000个唯一ID,这是非常缓慢的。
当然,我尝试了上面提到的Contains()
逻辑和先前请求的缓存数组。
其次,我尝试在SQL中创建一个数据表,以保存已保存搜索的ID,每个结果ID都在其自己的行中。这对原始问题没有任何帮助。
接下来,我阅读了C#HashSets
并尝试将firstSearchResults
转换为HashSet
,然后在.Contains()
扩展程序中使用它。这似乎有所帮助,但还不够,因为我的一些搜索仍然需要4-5分钟才能返回结果。
我也试过.Join()
但编译器抱怨我无法在return语句中重构我的对象实例。
我查看了.Intersect
,但这需要我在firstSearchResults
和results
IQueryable之间创建一个新的交叉ID列表。然后,我必须列举整个事情来获得最终的结果列表。由于我正在分页结果集,因此我需要保持results
的可查询性,直到order
,skip
和take
为止。
最后,出于绝望,我开始编写一个SQL存储过程,在其中我将datatable
个id作为READONLY
参数传递,然后使用我的关键字函数的结果进行连接运行全文搜索。这可能有用,但SQL不是我的强项,我暂时放弃了追求这个帖子。
感谢任何帮助。
答案 0 :(得分:0)
.Intersect()
似乎在性能方面提供了最佳结果。
从算法上讲:
IQueryable
完全变异,然后从中选择一个唯一ID列表.Skip(n)
,.Take(n)
),您可以快速构建返回对象的子集。这是一个伪代码示例:
//current result set
var resultIds = iQueryableResults.Select(s => s.Id).ToArray();
//intersect with some other array of ints
var intersection = resultIds.Intersect(priorResults).ToArray();
//Total the results in the intersection
var resultCount = intersection.Count();
//Get an upper boundary for your loop.
var upperLimit = (resultCount >= ((filter.Skip + filter.Take) - 1))
? (filter.Skip + filter.Take) - 1
: resultCount;
var results = new List<MyReturnObject>();
//Back to the basics
for (int i = filter.Skip; i < upperLimit; i++)
{
var _id = intersection[i];
results.Add(QueryAllMyObjects().FirstOrDefault(f => f.Id == _id));
}
return results;
这不是优雅或漂亮的,但是它比在.Contains()
谓词中使用where
要快得多(与大约20-30k的id数组进行比较时大约需要2-3秒) IDS)。希望它可以帮助别人。