यदि आप "सटीक चीज़" को संदर्भित पोस्ट के रूप में .NET के साथ करने के लिए देख रहे हैं, तो शायद यह वास्तव में उस तरह लागू नहीं होने वाला है। आप ऐसा कर सकते हैं, लेकिन आप शायद सभी परेशानियों में नहीं जा रहे हैं और वास्तव में अन्य विकल्पों में से एक के लिए नहीं जा रहे हैं, जब तक कि आपको "लचीले अंतराल" की आवश्यकता न हो, जितना कि मैं करता हूं ..
फ्लुएंट एग्रीगेट
यदि आपके पास एक आधुनिक MongoDB 3.6 या उच्चतर सर्वर उपलब्ध है तो आप $dateFromParts
का उपयोग कर सकते हैं दिनांक से निकाले गए "गोलाकार" भागों से दिनांक का पुनर्निर्माण करने के लिए:
DateTime startDate = new DateTime(2018, 5, 1, 0, 0, 0, DateTimeKind.Utc);
DateTime endDate = new DateTime(2018, 6, 1, 0, 0, 0, DateTimeKind.Utc);
var result = Collection.Aggregate()
.Match(k => k.Timestamp >= startDate && k.Timestamp < endDate)
.Group(k =>
new DateTime(k.Timestamp.Year, k.Timestamp.Month, k.Timestamp.Day,
k.Timestamp.Hour, k.Timestamp.Minute - (k.Timestamp.Minute % 15), 0),
g => new { _id = g.Key, count = g.Count() }
)
.SortBy(d => d._id)
.ToList();
सर्वर को भेजा गया विवरण:
[
{ "$match" : {
"Timestamp" : {
"$gte" : ISODate("2018-05-01T00:00:00Z"),
"$lt" : ISODate("2018-06-01T00:00:00Z")
}
} },
{ "$group" : {
"_id" : {
"$dateFromParts" : {
"year" : { "$year" : "$Timestamp" },
"month" : { "$month" : "$Timestamp" },
"day" : { "$dayOfMonth" : "$Timestamp" },
"hour" : { "$hour" : "$Timestamp" },
"minute" : { "$subtract" : [
{ "$minute" : "$Timestamp" },
{ "$mod" : [ { "$minute" : "$Timestamp" }, 15 ] }
] },
"second" : 0
}
},
"count" : { "$sum" : 1 }
} },
{ "$sort": { "_id": 1 } }
]
यदि आपके पास वह सुविधा उपलब्ध नहीं है, तो आप बस उसे छोड़ सकते हैं और दिनांक "असंबद्ध" छोड़ सकते हैं, लेकिन फिर कर्सर को संसाधित करते समय इसे फिर से इकट्ठा कर सकते हैं। बस एक सूची के साथ अनुकरण करने के लिए:
var result = Collection.Aggregate()
.Match(k => k.Timestamp >= startDate && k.Timestamp < endDate)
.Group(k => new
{
year = k.Timestamp.Year,
month = k.Timestamp.Month,
day = k.Timestamp.Day,
hour = k.Timestamp.Hour,
minute = k.Timestamp.Minute - (k.Timestamp.Minute % 15)
},
g => new { _id = g.Key, count = g.Count() }
)
.SortBy(d => d._id)
.ToList();
foreach (var doc in result)
{
//System.Console.WriteLine(doc.ToBsonDocument());
System.Console.WriteLine(
new BsonDocument {
{ "_id", new DateTime(doc._id.year, doc._id.month, doc._id.day,
doc._id.hour, doc._id.minute, 0) },
{ "count", doc.count }
}
);
}
सर्वर को भेजा गया विवरण:
[
{ "$match" : {
"Timestamp" : {
"$gte" : ISODate("2018-05-01T00:00:00Z"),
"$lt" : ISODate("2018-06-01T00:00:00Z")
}
} },
{ "$group" : {
"_id" : {
"year" : { "$year" : "$Timestamp" },
"month" : { "$month" : "$Timestamp" },
"day" : { "$dayOfMonth" : "$Timestamp" },
"hour" : { "$hour" : "$Timestamp" },
"minute" : { "$subtract" : [
{ "$minute" : "$Timestamp" },
{ "$mod" : [ { "$minute" : "$Timestamp" }, 15 ] }
] }
},
"count" : { "$sum" : 1 }
} },
{ "$sort" : { "_id" : 1 } }
]
कोड के संदर्भ में दोनों के बीच बहुत कम अंतर है। यह सिर्फ इतना है कि एक मामले में DateTime
. पर "वापस कास्टिंग" वास्तव में सर्वर पर $dateFromParts
. के साथ होता है और दूसरे में हम DateTime
. का उपयोग करके ठीक वही कास्टिंग करते हैं कोड में कंस्ट्रक्टर जैसा कि आप प्रत्येक कर्सर परिणाम को पुनरावृत्त करते हैं।
तो वे वास्तव में लगभग एक ही वास्तविक अंतर के साथ समान हैं जहां "सर्वर" कास्टिंग की तारीख लौटाता है, प्रति दस्तावेज़ बहुत कम बाइट्स का उपयोग करता है। वास्तव में "5 गुना" कम क्योंकि यहां सभी संख्यात्मक प्रारूप (बीएसओएन दिनांक सहित) 64 बिट पूर्णांक पर आधारित हैं। फिर भी, वे सभी संख्याएँ वास्तव में किसी तिथि के किसी भी "स्ट्रिंग" प्रतिनिधित्व को वापस भेजने की तुलना में वास्तव में "हल्का" हैं।
LINQ क्वेरी करने योग्य
वे मूल रूप हैं जो इन विभिन्न रूपों पर मानचित्रण करते समय वास्तव में वही रहते हैं:
var query = from p in Collection.AsQueryable()
where p.Timestamp >= startDate && p.Timestamp < endDate
group p by new DateTime(p.Timestamp.Year, p.Timestamp.Month, p.Timestamp.Day,
p.Timestamp.Hour, p.Timestamp.Minute - (p.Timestamp.Minute % 15), 0) into g
orderby g.Key
select new { _id = g.Key, count = g.Count() };
सर्वर को भेजा गया विवरण:
[
{ "$match" : {
"Timestamp" : {
"$gte" : ISODate("2018-05-01T00:00:00Z"),
"$lt" : ISODate("2018-06-01T00:00:00Z")
}
} },
{ "$group" : {
"_id" : {
"$dateFromParts" : {
"year" : { "$year" : "$Timestamp" },
"month" : { "$month" : "$Timestamp" },
"day" : { "$dayOfMonth" : "$Timestamp" },
"hour" : { "$hour" : "$Timestamp" },
"minute" : { "$subtract" : [
{ "$minute" : "$Timestamp" },
{ "$mod" : [ { "$minute" : "$Timestamp" }, 15 ] }
] },
"second" : 0
}
},
"__agg0" : { "$sum" : 1 }
} },
{ "$sort" : { "_id" : 1 } },
{ "$project" : { "_id" : "$_id", "count" : "$__agg0" } }
]
या GroupBy()
का उपयोग कर रहे हैं
var query = Collection.AsQueryable()
.Where(k => k.Timestamp >= startDate && k.Timestamp < endDate)
.GroupBy(k =>
new DateTime(k.Timestamp.Year, k.Timestamp.Month, k.Timestamp.Day,
k.Timestamp.Hour, k.Timestamp.Minute - (k.Timestamp.Minute % 15), 0),
(k, s) => new { _id = k, count = s.Count() }
)
.OrderBy(k => k._id);
सर्वर को भेजा गया विवरण:
[
{ "$match" : {
"Timestamp" : {
"$gte" : ISODate("2018-05-01T00:00:00Z"),
"$lt" : ISODate("2018-06-01T00:00:00Z")
}
} },
{ "$group" : {
"_id" : {
"$dateFromParts" : {
"year" : { "$year" : "$Timestamp" },
"month" : { "$month" : "$Timestamp" },
"day" : { "$dayOfMonth" : "$Timestamp" },
"hour" : { "$hour" : "$Timestamp" },
"minute" : { "$subtract" : [
{ "$minute" : "$Timestamp" },
{ "$mod" : [ { "$minute" : "$Timestamp" }, 15 ] }
] },
"second" : 0
}
},
"count" : { "$sum" : 1 }
} },
{ "$sort" : { "_id" : 1 } }
]
जैसा कि आप देख सकते हैं कि यह मूल रूप से एक ही रूप है
मूल को रूपांतरित करना
यदि आप पोस्ट किए गए मूल "तिथि गणित" फॉर्म को दोहराने की तलाश में हैं, तो यह वर्तमान में LINQ या फ्लुएंट बिल्डर्स के साथ वास्तव में आप जो कर सकते हैं उसके दायरे से परे है। उसी क्रम को प्राप्त करने का एकमात्र तरीका BsonDocument
. के साथ है निर्माण:
DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
var group = new BsonDocument { {
"$group",
new BsonDocument {
{ "_id",
new BsonDocument { {
"$add", new BsonArray
{
new BsonDocument { {
"$subtract",
new BsonArray {
new BsonDocument { { "$subtract", new BsonArray { "$Timestamp", epoch } } },
new BsonDocument { {
"$mod", new BsonArray
{
new BsonDocument { { "$subtract", new BsonArray { "$Timestamp", epoch } } },
1000 * 60 * 15
}
} }
}
} },
epoch
}
} }
},
{
"count", new BsonDocument("$sum", 1)
}
}
} };
var query = sales.Aggregate()
.Match(k => k.Timestamp >= startDate && k.Timestamp < endDate)
.AppendStage<BsonDocument>(group)
.Sort(new BsonDocument("_id", 1))
.ToList();
सर्वर को अनुरोध भेजा गया:
[
{ "$match" : {
"Timestamp" : {
"$gte" : ISODate("2018-05-01T00:00:00Z"),
"$lt" : ISODate("2018-06-01T00:00:00Z")
}
} },
{ "$group" : {
"_id" : {
"$add" : [
{ "$subtract" : [
{ "$subtract" : [ "$Timestamp", ISODate("1970-01-01T00:00:00Z") ] },
{ "$mod" : [
{ "$subtract" : [ "$Timestamp", ISODate("1970-01-01T00:00:00Z") ] },
900000
] }
] },
ISODate("1970-01-01T00:00:00Z")
]
},
"count" : { "$sum" : 1 }
} },
{ "$sort" : { "_id" : 1 } }
]
बड़ा कारण यह है कि हम अभी ऐसा नहीं कर सकते हैं क्योंकि बयानों का वर्तमान क्रमांकन मूल रूप से इस बात से असहमत है कि .NET Framework कहता है कि दो DateTime
घटाना मान एक TimeSpan
लौटाते हैं , और दो बीएसओएन तिथियों को घटाकर मोंगोडीबी निर्माण "युग के बाद से मिलीसेकंड" देता है, जो अनिवार्य रूप से गणित कैसे काम करता है।
लैम्ब्डा अभिव्यक्ति का "शाब्दिक" अनुवाद अनिवार्य रूप से है:
p => epoch.AddMilliseconds(
(p.Timestamp - epoch).TotalMilliseconds
- ((p.Timestamp - epoch).TotalMilliseconds % 1000 * 60 * 15))
लेकिन मैपिंग को अभी भी कुछ काम करने की ज़रूरत है ताकि या तो बयानों को पहचाना जा सके या औपचारिक रूप से इस उद्देश्य के लिए किस प्रकार के बयान वास्तव में अभिप्रेत हैं।
विशेष रूप से MongoDB 4.0 $convert
. का परिचय देता है ऑपरेटर और $toLong
. के सामान्य उपनाम और $toDate
, जो सभी बीएसओएन तिथियों के साथ "जोड़" और "घटाव" पर वर्तमान हैंडलिंग के स्थान पर पाइपलाइन में उपयोग किया जा सकता है। ये ऐसे रूपांतरणों के लिए अधिक "औपचारिक" विनिर्देश बनाना शुरू करते हैं, जैसा कि दिखाया गया है, जो पूरी तरह से उस "जोड़" और "घटाव" पर निर्भर करता है, जो अभी भी मान्य है, लेकिन ऐसे नामित ऑपरेटर कोड के भीतर इरादे के बारे में बहुत स्पष्ट हैं:
{ "$group": {
"_id": {
"$toDate": {
"$subtract": [
{ "$toLong": "$Timestamp" },
{ "$mod": [{ "$toLong": "$Timestamp" }, 1000 * 60 * 15 ] }
]
}
},
"count": { "$sum": 1 }
}}
यह देखने के लिए बहुत सादा है कि "औपचारिक" ऑपरेटरों के साथ LINQ के साथ इस तरह के "DateToLong" और "LongToDate" फ़ंक्शंस के लिए कथन निर्माण के लिए, फिर कथन "गैर-कामकाजी" लैम्ब्डा अभिव्यक्ति में दिखाए गए "जबरदस्ती" के प्रकारों के बिना बहुत साफ हो जाता है किया।