如何在MongoDB中查询数组中的单个嵌入文档?

时间:2015-11-17 14:50:24

标签: arrays node.js mongodb embedded-documents

我试图在MongoDB中查询数组中的单个嵌入式文档。我不知道我做错了什么。以编程方式,我将查询此文档并将新的嵌入文档插入当前空的trips数组中。

{
    "_id" : ObjectId("564b3300953d9d51429163c3"),
    "agency_key" : "DDOT",
    "routes" : [
        {
            "route_id" : "6165",
            "route_type" : "3",
            "trips" : [ ]
        },
        {
            "route_id" : "6170",
            "route_type" : "3",
            "trips" : [ ]
        },
...

    ]
}

以下查询 - 我在mongo shell中运行 - 返回空:

db.tm_routes.find( { routes :  {$elemMatch: { route_id:6165 } } } ).pretty();

db.tm_routes.find( { routes :  {$elemMatch: { route_id:6165,route_type:3 } } } ).pretty();

db.tm_routes.find({'routes.route_id':6165}).pretty()

db.tm_routes.find({'routes.route_id':6165}).count()也是0

以下查询返回数组中的每个文档

db.tm_routes.find({'routes.route_id':'6165'}).pretty();

{
    "_id" : ObjectId("564b3300953d9d51429163c3"),
    "agency_key" : "DDOT",
    "routes" : [
        {
            "route_id" : "6165",
            "route_type" : "3",
            "trips" : [ ]
        },
        {
            "route_id" : "6170",
            "route_type" : "3",
            "trips" : [ ]
        },
        ...
        ]}

db.tm_routes.find({'routes.route_id':'6165'}).count()返回1.

最后,这是我首先在Node.JS中插入数据的方法 - :

async.waterfall([
...
//RETRIEVE ALL ROUTEIDS FOR EVERY AGENCY
        function(agencyKeys, callback) {
          var routeIds = [];
          var routesArr = [];
          var routes = db.collection('routes'); 
//CALL GETROUTES FUNCTION FOR EVERY AGENCY
          async.map(agencyKeys, getRoutes, function(err, results){
            if (err) throw err;
            else {
              callback(null, results);
            }
          });
//GET ROUTE IDS
          function getRoutes(agencyKey, callback){
            var cursor = routes.find({agency_key:agencyKey});
            cursor.toArray(function(err, docs){
              if(err) throw err;
              for(i in docs){
                routeIds.push(docs[i].route_id);
                var routeObj = {
                  route_id:docs[i].route_id,
                  route_type:docs[i].route_type,
                  trips:[]
                };
                routesArr.push(routeObj);
    /* I TRIED 3 DIFFERENT WAYS TO PUSH DATA
//1->


        collection.update({agency_key:agencyKey}, {$push:{"routes":{
                  'route_id':docs[i].route_id,
                  'route_type':docs[i].route_type,
                  'trips':[]
                }}});
    //2->

collection.update({agency_key:agencyKey}, {$push:{"routes":routeObj}});

    */
                  }
    // 3->
                  collection.update({agency_key:agencyKey}, {$push:{routes:{$each:routesArr}}});
                  callback(null, routeIds);
                });
              };
            },
...

    var collection = newCollection(db, 'tm_routes',[]);
    function newCollection(db, name, options){
      var collection = db.collection(name);
      if (collection){
        collection.drop();
      }
      db.createCollection(name, options);
      return db.collection(name);
    }

注意:我没有使用Mongoose,如果可能的话也不想使用。

2 个答案:

答案 0 :(得分:2)

梅利斯,

我知道你要求的是什么,你需要的是帮助理解mongodb中存储事物的方式。需要了解的事情:

  • document是MongoDB的基本数据单元,可以与关系数据库中的row进行粗略比较。
  • 可以将collection视为具有动态架构的表

因此documents存储在collections中。每个文档都有一个特殊的_id,在集合中是唯一的。您通过以下格式向我们展示的内容是一个 document

{
    "_id" : ObjectId("564b3300953d9d51429163c3"),
    "agency_key" : "DDOT",
    "routes" : [
        {
            "route_id" : "6165",
            "route_type" : "3",
            "trips" : [ ]
        },
        {
            "route_id" : "6170",
            "route_type" : "3",
            "trips" : [ ]
        },
        ...
]}

如果您在query集合中运行tm_routesfind()将返回与该查询匹配的document中的每个collection。因此,当您运行查询db.tm_routes.find({'routes.route_id':'6165'}).pretty();时,它将返回与查询匹配的整个文档。因此这句话是错误的:

  

以下查询返回数组中的每个文档

如果您需要在该文档中找到特定路线,并且仅根据您的使用返回该路线,因为它是一个阵列,您可能必须使用$-Positional Operatoraggregation framework

答案 1 :(得分:0)

对于使用MongooseNode和Mongodb用户来说,这是针对上述问题编写查询的方法之一:

db.tm_routes.updateOne(
    {
      routes: {
        $elemMatch: {
          route_id: 6165 (or if its in a route path then **6165** could be replaced by **req.params.routeid**
        }
      }
    },
    {
       $push: {
         "routes.$.trips":{
             //the content you want to push into the trips array goes here
          }
       }
    }
)