MongoDB:使用同一查询中的查询结果在同一文档上

时间:2016-04-21 13:01:03

标签: mongodb mapreduce aggregation-framework

我正在尝试使用mongo db中的以下文档形成查询:

myMetaDataDoc document
{
  _id: <objectId>,
  tour: 
  {
    tourId: "TOURID1",
    stops: [{
      locationId: "LOC1",
      stopId: "STOPID1",
      ...
    ],[
      locationId: "LOC2",
      stopId: "STOPID2",
    ]}
  }
  schedule:{
    stopSchedules: [{
      stopId: "STOPID1"
      ...
    },{
      stopId: "STOPID2"
      ...
    }]
  }
}

基本上我想在一个地方获得各自的时间表信息。我需要一个查询来实现以下目标:

  1. 查询所有带位置的站点(例如,LOC1)
  2. 查询所有stopSchedules,其中stops.stopId为1。
  3. 返回止损+时间表
  4. 我尝试使用聚合,但无法在同一查询中使用stops.stopId。这是我的尝试:

    db.myMetaDataDoc.aggregate([
     {$match : {'tour.stops.locationId':'LOC1'}},    // all tour stops with locationId as LOC1
     {$unwind : '$tour.stops'},  // break all stops
     {$match : {'tour.stops.locationId':'LOC1'} },  // all tour with only stops with locationId as LOC1
     {$unwind : '$schedule.stopSchedules'}, // break all stopschedules
     {$match : {'schedule.stopSchedules.stopsId' : {$in :<stopId array>}} }  // missing array of stopId
    ])
    

    删除最后一个$ match,我收到所有行的单个&#34; tour.stops&#34;和单个&#34; schedules.stopSchedules&#34;。

    { "_id" : ObjectId("xx1"), "myMetaDataDoc" : {"tour" : { "tourId" : "TOURID1", "stops" : { "locationId" : "LOC1", "stopId" : "STOPID1"} } , "schedule" : { "stopSchedules" : { "stopId" : "STOPID1", ...}}}}
    { "_id" : ObjectId("xx2"), "myMetaDataDoc" : {"tour" : { "tourId" : "TOURID1", "stops" : { "locationId" : "LOC1", "stopId" : "STOPID1"} } , "schedule" : { "stopSchedules" : { "stopId" : "STOPID2", ...}}}}
    

    从这些行集中,我只需要那些stops.stopId等于schedules.stopSchedules.stopId的行。似乎聚合不喜欢$ where。我应该使用mapreduce()吗?还是服务器端脚本?

    感谢所有建议。

1 个答案:

答案 0 :(得分:0)

在尝试使用aggregate和$ eq运算符后,我认为我得到的东西接近我需要的东西。我做的是跳过最后一个匹配并使用$ eq运算符在所有行上使用具有有效字段的组。我后来使用投影将其删除。

db.myMetaDataDoc.aggregate([
 {$match : {'tour.stops.locationId':'LOC1'}},    // all tour stops with locationId as LOC1
 {$unwind : '$tour.stops'},  // break all stops
 {$match : {'tour.stops.locationId':'LOC1'} },  // all tour with only stops with locationId as LOC1
 {$unwind : '$schedule.stopSchedules'}, // break all stopschedules
 {$group : { 
    '_id': '$tour.tourId', 
    valid: {$first: {$cond: [{$eq: ['$tour.stops.stopId','$schedule.stopSchedules.stopId']}, '1', '0']}},    // validate row 
    stop : { $first: '$tour.stops'}, 
    schedule : {$first: '$schedule.stopSchedules'}
 {$match : {'valid':'1'} },    // skip invalid rows
 {
    $project: {            // remove valid field
        _id: 1,
        stop: 1,
        schedule:1
    }
 }
])

我仍然愿意接受更好的解决方案。