2016-03-30 12 views
4

Bir isteğe bağlı olarak bir diziden birden çok değer almam gereken bir durum var. veritabanında şeylerdenBirden Fazla Kritere Göre Bir Diziden Birden Fazla Nesne Çekme

Devlet:

{ 
    "_id" : ObjectId("56fb8fdf5e3227c637891ca8"), 
    "description" : "Testing service", 
    "name" : "test-service", 
    "endpoints" : [ 
     { 
      "uri" : "/api/test1", 
      "method" : "GET", 
      "description" : "test1", 
      "noAuthRequired" : true, 
      "allowedByDefault" : true, 
      "allowedRoles" : ['admin'] 
     }, 
     { 
      "uri" : "/api/test2", 
      "method" : "GET", 
      "description" : "test2", 
      "noAuthRequired" : true, 
      "allowedByDefault" : true, 
      "allowedRoles" : ['admin'] 
     }, 
     { 
      "uri" : "/api/test3", 
      "method" : "GET", 
      "description" : "test3", 
      "noAuthRequired" : true, 
      "allowedByDefault" : true, 
      "allowedRoles" : ['admin'] 
     } 
    ] 
} 

İstekler ben veritabanı diziden kaldırılmalıdır birden uç noktaları sıralar. JSON istek örneği:

{ 
    "endpoints": [{ 
     "uri": "/api/test1", 
     "method": "GET" 
    }, 
    { 
     "uri": "/api/test2", 
     "method": "POST" 
    }] 
} 

bu istek geliyor ve işlenen alır, bu URI/API/test1 ve yöntem GET ile bitiş noktası kaldırmalısınız. URI/api/test2 ile son noktayı kaldırmamalı ve GET beacuse isteği POST/api/test2'nin kaldırılması gerektiğini belirtti ve DB'de mevcut olmadığı için yalnızca GET/api/test1 kaldırıldı.

Mongoose kullanarak ben bu şekilde yapıyor denedim

:

router.route('/services/:id/endpoints').delete(function(req, res) { 
    ... 
    model.service.findOneAndUpdate({ '_id': req.params.id }, 
    { $pull: { 'endpoints': req.body.endpoints } }, 
    function(err, srv) { 
     ... 
    }); 
}); 

Ve bu hiç bir şey yapmaz.

router.route('/services/:id/endpoints').delete(function(req, res) { 
    ... 
    model.service.findOneAndUpdate({ '_id': req.params.id }, 
    { $pullAll: { 'endpoints': req.body.endpoints } }, 
    function(err, srv) { 
     ... 
    }); 
}); 

Bu, hiçbir şey yapmaz.

router.route('/services/:id/endpoints').delete(function(req, res) { 
    ... 
    model.service.findOneAndUpdate({ '_id': req.params.id }, 
    { $pullAll: { 'endpoints': { $in: req.body.endpoints } } }, 
    function(err, srv) { 
     ... 
    }); 
}); 

Ve bu, DB'deki son noktaların tümünü içermemelidir;

Ben uyumsuz kullanarak yerleşmiş:

var pullCalls = []; 
req.body.endpoints.forEach(function(endpoint) { 
    pullCalls.push(function(callback) { 
    model.service.findOneAndUpdate({ 
     '_id': req.params.id 
    }, { 
     $pull: { 
     'endpoints': { 
      'method': endpoint.method, 
      'uri': endpoint.uri 
     } 
     } 
    }, function(err, srv) { 
     if (err) 
     return callback(err); 
     callback(err, srv); 
    }); 
    }); 
}); 

// TODO: try doing this without async in a single query 
async.parallel(pullCalls, function(err, srv) { 
    if (err) { 
    res.status(500); 
    res.json({ 
     'success': false, 
     'response': err 
    }); 
    } else { 
    res.json({ 
     'success': true, 
     'response': 'endpoints_removed' 
    }); 
    } 
}); 

Ve bu çalışır, ancak ben tek firavunfaresi sorguda zaman uyumsuz gelmeden önce bunu istiyorum. Bunu yapmanın bir yolu var mı?

teşekkür ederiz :)

cevap

1

Öyle bu nefret edeceksiniz, ama:

{ "$pull": { "endpoints": { "$or": req.body.endpoints } } } 

gayet çalışacak.

$or işleci, verileri tam olarak gönderdiğiniz formla aynı şekilde bekler. Ve $pull zaten dizi alan elemanlarının doğaya göre incelenmesi üzerinde çalışıyor. temelde çevirir

Ve tabii $or aracı "ya"

, "bu durumlardan herhangi birine uyar şey, çekilecek gerekiyor".

Yani sürece aslında dediğin gibi bir dizi olarak temsil edilir req.body.endpoints olarak, o aslında teşekkür ederiz çalıştı $or

+0

doğru bir argümandır! Hatta $ veya varlığını bile bilmiyordum: D –

+0

@FilipVoska Aslında "$ in" ile çok yakın * değildiniz, ama elbette operatör "değerler" in yalnızca bir "listesini" ve "tam bir belge ifadesini" beklemiyor. . Bu yüzden teşebbüsünüz için sahne alıyorsunuz ve bu, burada bir çok insanın sorduğundan çok daha iyi. Ayrıca "$ in" in diziler için "özel" bir operatör olmadığını da şaşırtabilirsiniz. Tersine, bir alanın gerçekte bir dizinin kendisi olup olmadığına bakılmaksızın, "bir alanla eşleşecek argümanlar dizisi" olmaktır. Bunu düşünmenin en iyi yolu, "$ veya" için kısa yol "* şeklindedir. Aslında bu gerçekten. –