मूल रूप से एक $addToSet
डालें
ऑपरेटर आपके लिए काम नहीं कर सकता क्योंकि आपका डेटा सही नहीं है "set"
परिभाषा के अनुसार "पूरी तरह से अलग" वस्तुओं का संग्रह है।
यहां तार्किक अर्थ का दूसरा हिस्सा यह है कि आप डेटा के आने पर उस पर काम कर रहे होंगे, या तो एक पापी वस्तु या एक फ़ीड के रूप में। मैं मान लूंगा कि यह किसी न किसी रूप में कई मदों का फ़ीड है और आप इस संरचना को प्राप्त करने के लिए किसी प्रकार के स्ट्रीम प्रोसेसर का उपयोग कर सकते हैं:
{
"date": new Date("2015-03-09 13:23:00.000Z"),
"symbol": "AAPL",
"open": 127.14
"high": 127.17,
"low": 127.12
"close": 127.15,
"volume": 19734
}
एक मानक दशमलव प्रारूप के साथ-साथ एक यूटीसी तिथि में कनवर्ट करना क्योंकि निश्चित रूप से डेटास्टोर से डेटा पुनर्प्राप्त होने के बाद किसी भी लोकेल सेटिंग्स को वास्तव में आपके एप्लिकेशन का डोमेन होना चाहिए।
मैं कम से कम आपके "intraDayQuoteSchema" को दूसरे संग्रह के संदर्भ को हटाकर और केवल डेटा को वहां रखकर थोड़ा सा फ़्लैट कर दूंगा। आपको अभी भी सम्मिलन पर एक लुकअप की आवश्यकता होगी, लेकिन पढ़ने पर अतिरिक्त पॉप्युलेट का ओवरहेड स्टोरेज ओवरहेड की तुलना में अधिक महंगा प्रतीत होगा:
intradayQuotesSchema = Schema({
symbol:{
name: String,
code: String
},
day:Date,
quotes:[quotesSchema]
});
यह आपके उपयोग के पैटर्न पर निर्भर करता है, लेकिन यह उस तरह से अधिक प्रभावी होने की संभावना है।
बाकी वास्तव में नीचे आता है जो स्वीकार्य है
stream.on(function(data) {
var symbol = data.symbol,
myDay = new Date(
data.date.valueOf() -
( data.date.valueOf() % 1000 * 60 * 60 * 24 ));
delete data.symbol;
symbol.findOne({ "code": symbol },function(err,stock) {
intraDayQuote.findOneAndUpdate(
{ "symbol.code": symbol , "day": myDay },
{ "$setOnInsert": {
"symbol.name": stock.name
"quotes": [data]
}},
{ "upsert": true }
function(err,doc) {
intraDayQuote.findOneAndUpdate(
{
"symbol.code": symbol,
"day": myDay,
"quotes.date": data.date
},
{ "$set": { "quotes.$": data } },
function(err,doc) {
intraDayQuote.findOneAndUpdate(
{
"symbol.code": symbol,
"day": myDay,
"quotes.date": { "$ne": data.date }
},
{ "$push": { "quotes": data } },
function(err,doc) {
}
);
}
);
}
);
});
});
यदि आपको वास्तव में प्रतिक्रिया में संशोधित दस्तावेज़ की आवश्यकता नहीं है तो आपको यहां बल्क ऑपरेशंस एपीआई को लागू करके और इस पैकेज में सभी अपडेट एक डेटाबेस अनुरोध के भीतर भेजकर कुछ लाभ मिलेगा:
stream.on("data",function(data) {
var symbol = data.symbol,
myDay = new Date(
data.date.valueOf() -
( data.date.valueOf() % 1000 * 60 * 60 * 24 ));
delete data.symbol;
symbol.findOne({ "code": symbol },function(err,stock) {
var bulk = intraDayQuote.collection.initializeOrderedBulkOp();
bulk.find({ "symbol.code": symbol , "day": myDay })
.upsert().updateOne({
"$setOnInsert": {
"symbol.name": stock.name
"quotes": [data]
}
});
bulk.find({
"symbol.code": symbol,
"day": myDay,
"quotes.date": data.date
}).updateOne({
"$set": { "quotes.$": data }
});
bulk.find({
"symbol.code": symbol,
"day": myDay,
"quotes.date": { "$ne": data.date }
}).updateOne({
"$push": { "quotes": data }
});
bulk.execute(function(err,result) {
// maybe do something with the response
});
});
});
मुद्दा यह है कि वहां केवल एक बयान वास्तव में डेटा को संशोधित करेगा, और चूंकि यह सब एक ही अनुरोध में भेजा जाता है, इसलिए एप्लिकेशन और सर्वर के बीच कम आगे और पीछे होता है।
वैकल्पिक मामला यह है कि इस मामले में वास्तविक डेटा को किसी अन्य संग्रह में संदर्भित करना अधिक सरल हो सकता है। इसके बाद अप्सर्ट्स को प्रोसेस करने का एक साधारण मामला बन जाता है:
intradayQuotesSchema = Schema({
symbol:{
name: String,
code: String
},
day:Date,
quotes:[{ type: Schema.Types.ObjectId, ref: "quote" }]
});
// and in the steam processor
stream.on("data",function(data) {
var symbol = data.symbol,
myDay = new Date(
data.date.valueOf() -
( data.date.valueOf() % 1000 * 60 * 60 * 24 ));
delete data.symbol;
symbol.findOne({ "code": symbol },function(err,stock) {
quote.update(
{ "date": data.date },
{ "$setOnInsert": data },
{ "upsert": true },
function(err,num,raw) {
if ( !raw.updatedExisting ) {
intraDayQuote.update(
{ "symbol.code": symbol , "day": myDay },
{
"$setOnInsert": {
"symbol.name": stock.name
},
"$addToSet": { "quotes": data }
},
{ "upsert": true },
function(err,num,raw) {
}
);
}
}
);
});
});
यह वास्तव में नीचे आता है कि "दिन" दस्तावेज़ के भीतर उद्धरण चिह्नों के लिए डेटा होना आपके लिए कितना महत्वपूर्ण है। मुख्य अंतर यह है कि यदि आप डेटा के आधार पर उन दस्तावेज़ों को क्वेरी करना चाहते हैं तो उनमें से कुछ "उद्धरण" फ़ील्ड या अन्यथा .populate()
का उपयोग करने के ऊपरी भाग के साथ रहते हैं। दूसरे संग्रह से "उद्धरण" लेने के लिए।
बेशक यदि संदर्भित और उद्धरण डेटा आपकी क्वेरी फ़िल्टरिंग के लिए महत्वपूर्ण है, तो आप हमेशा उस संग्रह को _id
के लिए क्वेरी कर सकते हैं वे मान जो $in
"दिन" दस्तावेज़ों पर केवल उन दिनों से मेल खाने के लिए क्वेरी करें जिनमें वे "उद्धरण" दस्तावेज़ मेल खाते हों।
यह एक बड़ा निर्णय है जहां यह सबसे ज्यादा मायने रखता है कि आपका एप्लिकेशन डेटा का उपयोग कैसे करता है, इसके आधार पर आप कौन सा रास्ता अपनाते हैं। उम्मीद है कि यह आपको वह करने के पीछे की सामान्य अवधारणाओं पर मार्गदर्शन करेगा जो आप हासिल करना चाहते हैं।
पीएस जब तक आप "सुनिश्चित" नहीं हैं कि आपका स्रोत डेटा हमेशा एक सटीक "मिनट" के लिए एक तारीख है, तो आप शायद उसी तरह की तारीख को गोल करने वाले गणित को नियोजित करना चाहते हैं जैसा कि अलग "दिन" प्राप्त करने के लिए किया जाता है।