sql >> Databáze >  >> NoSQL >> MongoDB

Mongoose najít jeden a tlačit na pole dokumentů

V podstatě vložte $addToSet operátor pro vás nemůže pracovat, protože vaše data nejsou pravdivá "set" podle definice je souborem "zcela odlišných" objektů.

Dalším logickým smyslem je, že byste pracovali s daty tak, jak přicházejí, buď jako samostatný objekt nebo zdroj. Předpokládám, že se jedná o zdroj mnoha položek v nějaké formě a že můžete použít nějaký druh stream procesoru, abyste dosáhli této struktury na přijatý dokument:

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

Převod na standardní desítkový formát a také datum UTC, protože všechna nastavení národního prostředí by samozřejmě měla být doménou vaší aplikace, jakmile budou data načtena z datového úložiště.

Také bych alespoň trochu srovnal vaše „intraDayQuoteSchema“ odstraněním odkazu na druhou kolekci a pouze tam vložil data. Stále byste potřebovali vyhledávání při vkládání, ale režie dodatečného naplnění při čtení se zdá být nákladnější než režie úložiště:

intradayQuotesSchema = Schema({
    symbol:{
        name: String,
        code: String
    },
    day:Date,
    quotes:[quotesSchema]
});

Záleží na vašich způsobech používání, ale pravděpodobně to bude takto efektivnější.

Zbytek skutečně závisí na tom, co je přijatelné pro

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) {

                            }
                       );    
                    }
                );
            }
        );    
    });
});

Pokud upravený dokument v odpovědi ve skutečnosti nepotřebujete, získáte určitou výhodu implementací rozhraní API pro hromadné operace zde a odesláním všech aktualizací v tomto balíčku v rámci jednoho databázového požadavku:

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

Jde o to, že pouze jeden z tamních příkazů ve skutečnosti upraví data, a protože jsou všechny odeslány ve stejném požadavku, mezi aplikací a serverem je méně času.

Alternativním případem je, že v tomto případě může být jednodušší odkazovat na skutečná data v jiné kolekci. To se pak stává jednoduchou záležitostí zpracování upsertů:

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) {

                        }
                    );
                }
            }
        );
    });
});

Opravdu jde o to, jak důležité je pro vás mít data pro uvozovky vnořená do „denního“ dokumentu. Hlavním rozdílem je, pokud chcete tyto dokumenty dotazovat na základě dat některých z těchto polí „uvozovek“ nebo jinak žít s režií použití .populate() vytáhnout "uvozovky" z jiné kolekce.

Samozřejmě, pokud jsou pro filtrování dotazů důležité údaje o citacích a odkazech, pak můžete vždy jednoduše dotazovat tuto kolekci na _id hodnoty, které odpovídají a používají $in dotaz na dokumenty „den“, aby odpovídaly pouze dny, které obsahují tyto odpovídající dokumenty „citovat“.

Je to velké rozhodnutí, kde nejvíce záleží na tom, jakou cestou se vydáte na základě toho, jak vaše aplikace využívá data. Doufejme, že by vás to mělo vést k obecným konceptům, které stojí za tím, čeho chcete dosáhnout.

P.S. Pokud si nejste „jistí“, že vaše zdrojová data jsou vždy datum zaokrouhlené na přesnou „minutu“, pak pravděpodobně budete chtít použít stejný druh matematiky pro zaokrouhlování data, jaká byla použita pro získání diskrétního „dne“.




  1. MongoDB $acosh

  2. jak nainstalovat mongodb ovladače pro c++ v ubuntu?

  3. Časový limit připojení pro mongodb pomocí mongoose

  4. Regulární výraz MongoDB:Obsahuje e-mail uvnitř řetězce