排序C#Mongo查找结果以匹配搜索到的项目数组

问题描述 投票:1回答:1

背景:我们使用与我们的mongo分开的ElasticSearch来搜索事物。一旦查询返回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驱动程序可以为我做,那将是很酷的。

c# mongodb mongodb-.net-driver
1个回答
1
投票

没有一种好方法可以在MongoDB服务器端进行排序。即使有可能,我怀疑与客户端排序相比,您获得了一些性能提升。大部分时间用于从数据库读取数据并转移到客户端,这对于服务器和客户端排序是相同的。

你的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))的复杂性,这要好得多。

更新(关于不在问题中的代码):

我相信不工作代码你的意思是它无法编译。问题是Find方法返回IFindFluent<TDocument, TDocument>IFindFluent是一个游标,你不能直接在LINQ表达式中使用它。为了使你的代码编译和工作,在.ToEnumerable()结果上添加Find调用:

JobsCollection
    .Find(Builders<JobModel>.Filter.In(j => j.Id, idList))
    .ToEnumerable()
    .OrderBy(j => idList.IndexOf(j.Id));
© www.soinside.com 2019 - 2024. All rights reserved.