2

次のデータ構造があるとします。

{
"_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
        }
    ]
}

}

そして、一定期間の「SaleChanges」の値下げを見つける必要があります。

現在、mongodb、linq ベースのクエリ、およびいくつかの C# 拡張メソッドに C# ドライバーを使用しています。

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

このソリューションの主な問題は、パフォーマンスが失われることです。Mongo は、すべてのレコードを調べて計算を行う必要があります。これに代わるものはありますか?

4

1 に答える 1

0

price と salesChange.price の差を照会する必要がある場合は、計算された値を各項目とともに配列に格納することをお勧めします。各挿入および更新の前に設定するだけです。クエリでそのような計算値を取得するためのオプションがいくつかありますが、どの方法でも遅くなります。これが頻繁に行う必要がある場合は、挿入してインデックスを作成する前に設定してください。

より伝統的なデータベースで教育を受けた人々は、データを無意味に非正規化するという考えにうんざりしますが、Mongo はリレーショナル データベースではなく、ドキュメントに基づいています。一般に、ドキュメント全体が常にアトミックに更新されるため、ドキュメント内のデータを自由に非正規化できます。そのため、無効なデータになるリスクは同じではありません。

于 2014-02-06T19:13:57.567 に答える