对 C# Mongo 查找结果进行排序以匹配搜索的项目数组
Sort C# Mongo find results to match array of items that was searched for
背景:我们使用与 mongo 不同的 ElasticSearch 来搜索内容。一旦查询 returns 一个 id 列表,我们需要从 mongo 中提取项目并按照它们来自 ES 的顺序对它们进行排序。
问题:如何查找 ID 列表,然后将结果排序为与列表相同的顺序。它可能是这样的:
// NOTE: The following code does not work.
JobsCollection
.Find(Builders<JobModel>.Filter.In(j => j.Id, idList))
.OrderBy(j => idList.IndexOf(j.Id)) // <-- Something like this
如果我弄不明白,我可能会在拿到对象后对其进行排序,但是如果 mongo 驱动程序可以为我完成,那就太好了。
MongoDB服务器端没有一个很好的排序方法。即使有可能,我怀疑与客户端排序相比,您是否会获得一些性能改进。从DB中读取数据并传输到客户端花费的时间最多,这对于服务器端和客户端排序来说是相等的。
你的 LINQ 解决方案看起来很适合我。但是,它对每个列表元素使用 List.IndexOf()
,这给您 O(n^2) 的复杂性。此 LINQ 在大型列表中可能表现不佳。
我建议改进它并创建一个字典,将 id 值映射到它在列表中的索引:
var idMap = idList.Select((x, i) => new { Value = x, Index = i })
.ToDictionary(x => x.Value, x => x.Index);
var sorted = JobsCollection
.Find(Builders<JobModel>.Filter.In(j => j.Id, idList))
.ToList()
.OrderBy(j => idMap[j.Id]);
这将为您提供 O(n * log(n)) 的复杂度,这要好得多。
UPDATE(关于问题中的无效代码):
我相信代码不工作意味着它无法编译。问题是 Find
方法 returns IFindFluent<TDocument, TDocument>
。 IFindFluent
是一个游标,您不能直接在 LINQ 表达式中使用它。要使您的代码编译并工作,请添加 .ToEnumerable()
调用 Find
结果:
JobsCollection
.Find(Builders<JobModel>.Filter.In(j => j.Id, idList))
.ToEnumerable()
.OrderBy(j => idList.IndexOf(j.Id));
背景:我们使用与 mongo 不同的 ElasticSearch 来搜索内容。一旦查询 returns 一个 id 列表,我们需要从 mongo 中提取项目并按照它们来自 ES 的顺序对它们进行排序。
问题:如何查找 ID 列表,然后将结果排序为与列表相同的顺序。它可能是这样的:
// NOTE: The following code does not work.
JobsCollection
.Find(Builders<JobModel>.Filter.In(j => j.Id, idList))
.OrderBy(j => idList.IndexOf(j.Id)) // <-- Something like this
如果我弄不明白,我可能会在拿到对象后对其进行排序,但是如果 mongo 驱动程序可以为我完成,那就太好了。
MongoDB服务器端没有一个很好的排序方法。即使有可能,我怀疑与客户端排序相比,您是否会获得一些性能改进。从DB中读取数据并传输到客户端花费的时间最多,这对于服务器端和客户端排序来说是相等的。
你的 LINQ 解决方案看起来很适合我。但是,它对每个列表元素使用 List.IndexOf()
,这给您 O(n^2) 的复杂性。此 LINQ 在大型列表中可能表现不佳。
我建议改进它并创建一个字典,将 id 值映射到它在列表中的索引:
var idMap = idList.Select((x, i) => new { Value = x, Index = i })
.ToDictionary(x => x.Value, x => x.Index);
var sorted = JobsCollection
.Find(Builders<JobModel>.Filter.In(j => j.Id, idList))
.ToList()
.OrderBy(j => idMap[j.Id]);
这将为您提供 O(n * log(n)) 的复杂度,这要好得多。
UPDATE(关于问题中的无效代码):
我相信代码不工作意味着它无法编译。问题是 Find
方法 returns IFindFluent<TDocument, TDocument>
。 IFindFluent
是一个游标,您不能直接在 LINQ 表达式中使用它。要使您的代码编译并工作,请添加 .ToEnumerable()
调用 Find
结果:
JobsCollection
.Find(Builders<JobModel>.Filter.In(j => j.Id, idList))
.ToEnumerable()
.OrderBy(j => idList.IndexOf(j.Id));