MongoDB
 sql >> Baza danych >  >> NoSQL >> MongoDB

Jak usunąć obiekt biorąc pod uwagę referencje w Mongoose Node.js?

Musisz zagnieździć swoje wywołania, aby usunąć identyfikator produktu z innego modelu. Na przykład w swoim wezwaniu do usunięcia produktu z Produktu kolekcji, możesz również wykonać kolejne wywołanie, aby usunąć ref z Partnera model w wywołaniu zwrotnym wyników. Domyślne usunięcie produktu spowoduje usunięcie jego odnośników do Kampania Model.

Poniższy kod pokazuje powyższą intuicję:

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

Aby usunąć powiązane kampanie, możesz potrzebować dodatkowej operacji usuwania, która pobiera powiązany identyfikator kampanii z danego identyfikatora produktu. Rozważ następujący brudny hack, który może potencjalnie dać ci bilet w jedną stronę do piekielnego połączenia zwrotnego jeśli nie jesteś ostrożny z zagnieżdżaniem wywołań zwrotnych:

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

Chociaż to działa, powyższej potencjalnej pułapki można uniknąć, używając async/await lub async biblioteka. Ale po pierwsze, aby lepiej zrozumieć korzystanie z wielu wywołań zwrotnych z async zilustrujmy to przykładem z Seven Rzeczy, które powinieneś przestać robić z Node.js wielu operacji z wywołaniami zwrotnymi, aby znaleźć encję nadrzędną, a następnie znaleźć encje podrzędne należące do rodzica:

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

Dzięki async/await Twoje połączenia zostaną przekształcone w strukturę

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

Za pomocą modułu asynchronicznego możesz użyć metody serii, aby rozwiązać problem użycia wywołań zwrotnych do zagnieżdżania kodu wielu metod, co może skutkować Oddzwoń do piekła :

Seria :

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

Lub wodospad :

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

Teraz wracając do kodu, używając metody kaskadowej asynchronicznej, możesz następnie zmienić strukturę kodu 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. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Nie można pobrać danych z API przy użyciu Express NodeJS i MongoDB, ładowanie

  2. MongoDB Group używająca sterownika Ruby

  3. Indeks zakresu dat Mongo z filtrami

  4. Wzorzec modułu JavaScript z wywołaniem zwrotnym Ajax

  5. Połączenie AngularJS z MongoDB