2016-03-30 7 views
4

リクエストに基づいて配列から複数の値を取得する必要がある状況があります。データベースで物事の複数の条件で配列から複数のオブジェクトを取り出す方法

州:

{ 
    "_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'] 
     } 
    ] 
} 

要求は、私は、データベース配列から除去されなければならない複数のエンドポイントをリストアップ。

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

このリクエストが到着して処理されると、URI/api/test1およびメソッドGETを持つエンドポイントが削除されます。 URI/api/test2を持つエンドポイントを削除してはならず、メソッドGET beacuseリクエストは、POST/api/test2を削除する必要があり、DBには存在しないためGET/api/test1のみ削除されます。

マングースを使用して、私はそれをこのようにやって試してみました

、:

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

そして、それはまったく何もしません。

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

これは何もしません。

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

これにより、DB内のすべてのエンドポイントが削除されます。

私は非同期を使用して解決しています

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

そして、それは動作しますが、私は、単一のマングースクエリで非同期せずにそれをやってみたいと思います。それを行う方法はありますか?

ありがとうございました:)

答えて

1

をあなたはとてもこれを嫌いしようとしているが、:

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

がうまく動作します。

$orオペレータは、送信しているのとまったく同じ形式のデータが必要です。また、$pullはすでに配列フィールド要素の検査にも適用されています。

もちろん、$orは「どちらか」を意味し、基本的に「これらの条件のいずれかに一致するものは引っ張られる必要があります」となります。

だから限り、実際にあなたが言うような配列として表現されてreq.body.endpointsとして、それは実際にありがとう働いたこと$or

+0

に正しい引数です! D –

+0

@FilipVoskaあなたは実際には '$ in'で* close *でしたが、もちろん演算子は"値 "の"リスト "だけを期待し、"完全な文書式 "は期待していませんでした。 。だからあなたの試みの小道具、それはこれまで何度も求めている多くの人よりもはるかに優れています。また、 '$ in'は配列の演算子ではないことが混乱するかもしれません。それはむしろその逆であり、そのフィールドが実質的に配列自体であるかどうかにかかわらず、 "フィールドと一致する引数の配列"である。それを考えている最善の方法は、 "$または" *の省略形です。実際には、それは本当にです。 –

関連する問題