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