I have big LiteDB collection of items. I just want to find last one added by some criteria. Criteria are in lambda expression. My problem is, that it took realy long time (now around 2-3sec) and I just have testing database. In full mode, there will be 10 times more values.
My code now, with time stamps:
var values = db.GetCollection<ExtendedValue>(IncomingValueCollection);
if (values.Count() > 0) {
Stopwatch sw = new Stopwatch();
sw.Reset();
sw.Start();
var expressedVals = values.Find(lambda);
sw.Stop();
Debug.WriteLine("find values " + sw.ElapsedMilliseconds);
sw.Reset();
sw.Start();
var inOrder = expressedVals.OrderByDescending(x => x.TimeCaptured).Take(5);
sw.Stop();
Debug.WriteLine("order " + sw.ElapsedMilliseconds);
sw.Reset();
sw.Start();
var result = inOrder.First();
sw.Stop();
Debug.WriteLine("last " + sw.ElapsedMilliseconds);
return result;
//withouth stopwatch
//return values.Find(lambda).OrderByDescending(x => x.TimeCaptured).First();
}
and result is:
find values 0
order 0
last 2399
So it is clear, that pick value take most of time.
I have tried:
- Just use .First() on orderedEnum, no change
- use Take(x) or not, no change
- Convert it to Array or List and then pick first one, this take little longer, but nothing significant
I think, that .First() create array from enum and then pick first item. Is there any way to pick item withouth generating whole array and creating big lag?
EDIT: According to comments from Matthew Watson, i edited code, to find out, that my lambda expression take most of time and conclusion, that First() methot takes most time is mistake. It takes only becaouse it execute whole query at once.
if (values.Count() > 0) {
Stopwatch sw = new Stopwatch();
sw.Reset();
sw.Start();
var expressedVals = values.Find(lambda).ToList();
sw.Stop();
Debug.WriteLine("find values " + sw.ElapsedMilliseconds);
sw.Reset();
sw.Start();
var inOrder = expressedVals.OrderByDescending(x => x.TimeCaptured).ToList();
sw.Stop();
Debug.WriteLine("order " + sw.ElapsedMilliseconds);
sw.Reset();
sw.Start();
var result = expressedVals.First();
sw.Stop();
Debug.WriteLine("last " + sw.ElapsedMilliseconds);
return result;
//withouth stopwatch
//return values.Find(lambda).OrderByDescending(x => x.TimeCaptured).First();
with result
find values 2395
order 4
last 0
So I think, that I cannot do it this way, I have to create workaround.