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

Jak odstranit objekt s ohledem na reference v Mongoose Node.js?

Chcete-li odstranit ID produktu z druhého modelu, museli byste svá volání vnořit. Například ve vaší výzvě k odstranění produktu z Product kolekce, můžete také provést další volání k odstranění ref z Partner model v rámci zpětného volání výsledků. Odstraněním produktu ve výchozím nastavení odstraníte jeho odkazy na Campaign Modelka.

Následující kód ukazuje výše uvedenou intuici:

var campSchema = require('../model/camp-schema');

router.post('/removeProduct', function (req, res) {
    campSchema.Product.findOneAndRemove({ _id: req.body.productId }, function (err, response) {
        if (err) throw err;
        campSchema.Partner.update(
            { "products": req.body.productId },
            { "$pull": { "products": req.body.productId } },
            function (err, res){
                if (err) throw err;
                res.json(res);
            }
        );
    });
});

Chcete-li odstranit přidružené kampaně, možná budete potřebovat další operaci odstranění, která převezme ID přidružené kampaně z daného ID produktu. Zvažte následující špinavý hack, který vám může potenciálně udělit jednosměrnou letenku do callback hell pokud si nedáte pozor na vnoření zpětného volání:

router.post('/removeProduct', function (req, res) {
    campSchema.Product.findOneAndRemove(
        { _id: req.body.productId }, 
        { new: true },
        function (err, product) {
            if (err) throw err;
            campSchema.Partner.update(
                { "products": req.body.productId },
                { "$pull": { "products": req.body.productId } },
                function (err, res){
                    if (err) throw err;
                    var campaignList = product.campaign
                    campSchema.Campaign.remove({ "_id": { "$in": campaignList } })
                                .exec(function (err, res){
                                    if (err) throw err;
                                    res.json(product);
                                })
                }
            );
        }
    );
});

I když to funguje, výše uvedené potenciální úskalí se lze vyhnout použitím async/await nebo async knihovna. Ale za prvé, abychom vám lépe porozuměli používání vícenásobných zpětných volání pomocí async kód> modulu, pojďme si to ilustrovat na příkladu z Seven Věci, které byste měli přestat dělat s Node.js více operací se zpětnými voláními k nalezení nadřazené entity a poté nalezení podřízených entit, které patří nadřazené entitě:

methodA(function(a){
    methodB(function(b){
        methodC(function(c){
            methodD(function(d){
                // Final callback code        
            })
        })
    })
})

Při async/wait budou vaše hovory restrukturalizovány jako

router.post('/removeProduct', async (req, res) => {
    try {
        const product = await campSchema.Product.findOneAndRemove(
            { _id: req.body.productId }, 
            { new: true }
        )

        await campSchema.Partner.update(
            { "products": req.body.productId },
            { "$pull": { "products": req.body.productId } }
        )

        await campSchema.Campaign.remove({ "_id": { "$in": product.campaign } })

        res.json(product)
    } catch(err) {
        throw err
    }
})

S asynchronním modulem můžete buď použít metodu série k řešení použití zpětných volání pro vnořování kódu více metod, což může mít za následek Callback Hell :

Série :

async.series([
    function(callback){
        // code a
        callback(null, 'a')
    },
    function(callback){
        // code b
        callback(null, 'b')
    },
    function(callback){
        // code c
        callback(null, 'c')
    },
    function(callback){
        // code d
        callback(null, 'd')
    }],
    // optional callback
    function(err, results){
        // results is ['a', 'b', 'c', 'd']
        // final callback code
    }
)

Nebo vodopád :

async.waterfall([
    function(callback){
        // code a
        callback(null, 'a', 'b')
    },
    function(arg1, arg2, callback){
        // arg1 is equals 'a' and arg2 is 'b'
        // Code c
        callback(null, 'c')
    },
    function(arg1, callback){      
        // arg1 is 'c'
        // code d
        callback(null, 'd');
    }], function (err, result) {
        // result is 'd'    
    }
)

Nyní se vraťte ke svému kódu a pomocí metody async waterfall byste pak mohli restrukturalizovat svůj kód na

router.post('/removeProduct', function (req, res) {
    async.waterfall([
        function (callback) {
            // code a: Remove Product
            campSchema.Product.findOneAndRemove(
                { _id: req.body.productId }, 
                function (err, product) {
                    if (err) callback(err);
                    callback(null, product);
                }
            );
        },

        function (doc, callback) {
            // code b: Remove associated campaigns
            var campaignList = doc.campaign;
            campSchema.Campaign
                .remove({ "_id": { "$in": campaignList } })
                .exec(function (err, res) {
                if (err) callback(err);
                callback(null, doc);
            }
            );
        },

        function (doc, callback) {
            // code c: Remove related partner
            campSchema.Partner.update(
                { "products": doc._id },
                { "$pull": { "products": doc._id } },
                function (err, res) {
                    if (err) callback(err);
                    callback(null, doc);
                }
            );
        }
    ], function (err, result) {
        if (err) throw err;
        res.json(result);  // OUTPUT OK
    });
});



  1. Jaká jsou omezení dílčích indexů?

  2. Odstraňte duplicitní záznamy z mongodb 4.0

  3. Nainstalujte CouchDB na Debian 9

  4. MongoDB $elemMatch $in