Background: We are using ElasticSearch separate from our mongo to search for things. Once the query returns a list of id's we need to pull the items from mongo and have them sorted in the order they came from ES.
Question: How do I find a list of id's then sort the results to be in the same order that the list is. It would maybe be something like this:
// 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
I may just sort it after I get the objects if I can't figure it out, but if the mongo driver can do it for me, that would be cool.
There is no a good way to make a sorting you described on MongoDB server side. And even if it was possible I doubt you gain some performance improvement comparing to client side sorting. The most time will be spent for reading the data from DB and transfering to the client, which are equal for server and client sorting.
Your LINQ solution looks good for me. However it uses List.IndexOf()
for each list element that gives you complexity of O(n^2). This LINQ could show poor performance on big lists.
I propose to improve it and create a dictionary that maps id value to its index in the list:
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]);
This will give you complexity of O(n * log(n)) which is far better.
UPDATE (regarding not working code from the question):
I believe by not working code you mean that it could not be compiled. The problem is that Find
method returns IFindFluent<TDocument, TDocument>
. IFindFluent
is an cursor and you can't use it in LINQ expressions directly. To make your code compile and work add .ToEnumerable()
call on Find
result:
JobsCollection
.Find(Builders<JobModel>.Filter.In(j => j.Id, idList))
.ToEnumerable()
.OrderBy(j => idList.IndexOf(j.Id));