Say I have following data structure:
{
"_id" : LUUID("d14c526e-34ba-4c41-9bb0-3bc32d9de106"),
"Address" : {
"Street" : "Winner street",
"HouseNo" : "776",
"PostalCode" : 9619,
"City" : "Majestic"
},
"Sales" : {
"Price" : 1315000,
"Submitted" : ISODate("2013-07-31T16:30:00Z"),
"SaleChanges" : [
{
"ChangeDate" : ISODate("2013-08-01T14:40:18Z"),
"Price" : 1795000
},
{
"ChangeDate" : ISODate("2013-08-03T14:40:18Z"),
"Price" : 1340000
}
]
}
}
And I need to find price decreases for "SaleChanges" for some period of time.
Now I'm using C# driver for mongodb, linq based query and some C# extensions methods:
internal static bool HasPriceDecreasesInLastSpan(this SaleModel sales, TimeSpan span, DateTime from)
{
var date = from;
var dateSpanBefore = date.Subtract(span);
var salesHistory = new List<PreviousSaleModel>();
var lastSale = sales.SaleChanges.OrderByDescending(s => s.ChangeDate).FirstOrDefault();
if (lastSale != null)
{
salesHistory.Add(new PreviousSaleModel()
{
ChangeDate = lastSale.ChangeDate,
Price = sales.Price
});
}
salesHistory.AddRange(sales.SaleChanges.Where((sc => sc.ChangeDate >= dateSpanBefore && sc.ChangeDate <= from)));
return salesHistory.HasPriceDecreases();
}
internal static bool HasPriceDecreases(this IEnumerable<PreviousSaleModel> salesHistory)
{
using (var e = salesHistory.OrderByDescending(key => key.ChangeDate).GetEnumerator())
{
var buffer = new List<PreviousSaleModel>();
while (e.MoveNext())
{
foreach (var item in buffer)
{
if (item.Price < e.Current.Price)
return true;
}
buffer.Add(e.Current);
}
}
return false;
}
var predicate = new Func<UnitModel, bool>(bm => bm.Sales != null && bm.Sales.SaleChanges.Count > 0 && bm.Sales.HasPriceDecreasesInLastNDays(days, fromDate));
_query = _query.Where(predicate).AsQueryable();
Main problem with this solution is performance lost. Mongo should look inside every record to make computations. Is there alternatives to this?