Mongodb 使用聚合框架比较数组元素重叠

Mongodb 使用聚合框架比较数组元素重叠,mongodb,aggregation-framework,Mongodb,Aggregation Framework,我有一个文档集,其结构如下: { carrier: "abc", flightNumber: 123, dates: [ ISODate("2015-01-01T00:00:00Z"), ISODate("2015-01-02T00:00:00Z"), ISODate("2015-01-03T00:00:00Z") ] } db.flights.aggregate([ { $group: { _id:

我有一个文档集,其结构如下:

{
   carrier: "abc",
   flightNumber: 123,
   dates: [
      ISODate("2015-01-01T00:00:00Z"),
      ISODate("2015-01-02T00:00:00Z"),
      ISODate("2015-01-03T00:00:00Z")
    ]
}
db.flights.aggregate([
  { 
    $group: { 
       _id: { carrier: "$carrier", flightNumber: "$flightNumber" }, 
       uniqueIds: { $addToSet: "$_id" },
       count: { $sum: 1 } 
    }
  }, 
  { 
    $match: { 
       count: { $gt: 1 } 
    }
  }
])
我想搜索收藏,看看是否有任何文档具有相同的
承运人
航班号
,并且
日期
数组中的日期也超过了圈数。例如:

{
   carrier: "abc",
   flightNumber: 123,
   dates: [
      ISODate("2015-01-01T00:00:00Z"),
      ISODate("2015-01-02T00:00:00Z"),
      ISODate("2015-01-03T00:00:00Z")
    ]
},
{
   carrier: "abc",
   flightNumber: 123,
   dates: [
      ISODate("2015-01-03T00:00:00Z"),
      ISODate("2015-01-04T00:00:00Z"),
      ISODate("2015-01-05T00:00:00Z")
    ]
}
如果上述记录存在于收藏中,我想将其退回,因为它们都有
承运人
abc
航班号
123
,并且在
日期
数组中也有日期
ISODate(“2015-01-03T00:00:00Z”)
。如果第二份文件中没有该日期,则不应返回

通常,我会通过如下方式分组和计数:

{
   carrier: "abc",
   flightNumber: 123,
   dates: [
      ISODate("2015-01-01T00:00:00Z"),
      ISODate("2015-01-02T00:00:00Z"),
      ISODate("2015-01-03T00:00:00Z")
    ]
}
db.flights.aggregate([
  { 
    $group: { 
       _id: { carrier: "$carrier", flightNumber: "$flightNumber" }, 
       uniqueIds: { $addToSet: "$_id" },
       count: { $sum: 1 } 
    }
  }, 
  { 
    $match: { 
       count: { $gt: 1 } 
    }
  }
])
但我不确定如何修改它以查找数组重叠。有人能建议如何实现这一点吗?

如果您想查看其中的“分组”内容,请使用数组:

db.flights.aggregate([
  { "$unwind": "$dates" },
  { "$group": {
    "_id": { "carrier": "$carrier", "flightnumber": "$flightnumber", "date": "$dates" },
     "count": { "$sum": 1 },
     "_ids": { "$addToSet": "$_id" }
  }},
  { "$match": { "count": { "$gt": 1 } } },
  { "$unwind": "$_ids" },
  { "$group": { "_id": "$_ids" } }
])
事实上,这会告诉您“重叠”所在的文档,因为“相同日期”以及您关心的其他相同分组键值有一个“计数”,它出现了不止一次。表示重叠

后面的任何内容实际上都只是为了“演示”,因为如果您只想查看重叠,则没有必要为多个重叠报告相同的
\u id
值。事实上,如果您想看到它们在一起,最好不要使用“分组集”

现在,如果检索实际文档对您很重要,您可以添加:

db.flights.aggregate([
  { "$unwind": "$dates" },
  { "$group": {
    "_id": { "carrier": "$carrier", "flightnumber": "$flightnumber", "date": "$dates" },
     "count": { "$sum": 1 },
     "_ids": { "$addToSet": "$_id" }
  }},
  { "$match": { "count": { "$gt": 1 } } },
  { "$unwind": "$_ids" },
  { "$group": { "_id": "$_ids" } },
  }},
  { "$lookup": {
    "from": "flights",
    "localField": "_id",
    "foreignField": "_id",
    "as": "_ids"
  }},
  { "$unwind": "$_ids" },
  { "$replaceRoot": {
    "newRoot": "$_ids"
  }}
])
甚至做一个或让它返回整个文件。或者,如果不是尺寸问题,你甚至可以用它

但总的来说,这一点是在管道的前三个阶段,或者主要是在“第一个”阶段。如果您想“跨文档”使用数组,那么主操作符仍然是


或者,对于更类似于“报告”的格式:

db.flights.aggregate([
  { "$addFields": { "copy": "$$ROOT" } }, 
  { "$unwind": "$dates" },
  { "$group": {
    "_id": {
      "carrier": "$carrier",
      "flightNumber": "$flightNumber",
      "dates": "$dates" 
    },
    "count": { "$sum": 1 },
    "_docs": { "$addToSet": "$copy" }  
  }},
  { "$match": { "count": { "$gt": 1 } } },
  { "$group": {
    "_id": {
      "carrier": "$_id.carrier",
      "flightNumber": "$_id.flightNumber",
    },
    "overlaps": {
      "$push": {
        "date": "$_id.dates",
        "_docs": "$_docs"  
      }  
    }  
  }}
])
这将报告每个组内的重叠日期,并告诉您哪些文档包含重叠:

{
    "_id" : {
        "carrier" : "abc",
        "flightNumber" : 123.0
    },
    "overlaps" : [ 
        {
            "date" : ISODate("2015-01-03T00:00:00.000Z"),
            "_docs" : [ 
                {
                    "_id" : ObjectId("5977f9187dcd6a5f6a9b4b97"),
                    "carrier" : "abc",
                    "flightNumber" : 123.0,
                    "dates" : [ 
                        ISODate("2015-01-03T00:00:00.000Z"), 
                        ISODate("2015-01-04T00:00:00.000Z"), 
                        ISODate("2015-01-05T00:00:00.000Z")
                    ]
                }, 
                {
                    "_id" : ObjectId("5977f9187dcd6a5f6a9b4b96"),
                    "carrier" : "abc",
                    "flightNumber" : 123.0,
                    "dates" : [ 
                        ISODate("2015-01-01T00:00:00.000Z"), 
                        ISODate("2015-01-02T00:00:00.000Z"), 
                        ISODate("2015-01-03T00:00:00.000Z")
                    ]
                }
            ]
        }
    ]
}
如果要将内容视为其中的“分组”内容,则可以使用数组:

db.flights.aggregate([
  { "$unwind": "$dates" },
  { "$group": {
    "_id": { "carrier": "$carrier", "flightnumber": "$flightnumber", "date": "$dates" },
     "count": { "$sum": 1 },
     "_ids": { "$addToSet": "$_id" }
  }},
  { "$match": { "count": { "$gt": 1 } } },
  { "$unwind": "$_ids" },
  { "$group": { "_id": "$_ids" } }
])
事实上,这会告诉您“重叠”所在的文档,因为“相同日期”以及您关心的其他相同分组键值有一个“计数”,它出现了不止一次。表示重叠

后面的任何内容实际上都只是为了“演示”,因为如果您只想查看重叠,则没有必要为多个重叠报告相同的
\u id
值。事实上,如果您想看到它们在一起,最好不要使用“分组集”

现在,如果检索实际文档对您很重要,您可以添加:

db.flights.aggregate([
  { "$unwind": "$dates" },
  { "$group": {
    "_id": { "carrier": "$carrier", "flightnumber": "$flightnumber", "date": "$dates" },
     "count": { "$sum": 1 },
     "_ids": { "$addToSet": "$_id" }
  }},
  { "$match": { "count": { "$gt": 1 } } },
  { "$unwind": "$_ids" },
  { "$group": { "_id": "$_ids" } },
  }},
  { "$lookup": {
    "from": "flights",
    "localField": "_id",
    "foreignField": "_id",
    "as": "_ids"
  }},
  { "$unwind": "$_ids" },
  { "$replaceRoot": {
    "newRoot": "$_ids"
  }}
])
甚至做一个或让它返回整个文件。或者,如果不是尺寸问题,你甚至可以用它

但总的来说,这一点是在管道的前三个阶段,或者主要是在“第一个”阶段。如果您想“跨文档”使用数组,那么主操作符仍然是


或者,对于更类似于“报告”的格式:

db.flights.aggregate([
  { "$addFields": { "copy": "$$ROOT" } }, 
  { "$unwind": "$dates" },
  { "$group": {
    "_id": {
      "carrier": "$carrier",
      "flightNumber": "$flightNumber",
      "dates": "$dates" 
    },
    "count": { "$sum": 1 },
    "_docs": { "$addToSet": "$copy" }  
  }},
  { "$match": { "count": { "$gt": 1 } } },
  { "$group": {
    "_id": {
      "carrier": "$_id.carrier",
      "flightNumber": "$_id.flightNumber",
    },
    "overlaps": {
      "$push": {
        "date": "$_id.dates",
        "_docs": "$_docs"  
      }  
    }  
  }}
])
这将报告每个组内的重叠日期,并告诉您哪些文档包含重叠:

{
    "_id" : {
        "carrier" : "abc",
        "flightNumber" : 123.0
    },
    "overlaps" : [ 
        {
            "date" : ISODate("2015-01-03T00:00:00.000Z"),
            "_docs" : [ 
                {
                    "_id" : ObjectId("5977f9187dcd6a5f6a9b4b97"),
                    "carrier" : "abc",
                    "flightNumber" : 123.0,
                    "dates" : [ 
                        ISODate("2015-01-03T00:00:00.000Z"), 
                        ISODate("2015-01-04T00:00:00.000Z"), 
                        ISODate("2015-01-05T00:00:00.000Z")
                    ]
                }, 
                {
                    "_id" : ObjectId("5977f9187dcd6a5f6a9b4b96"),
                    "carrier" : "abc",
                    "flightNumber" : 123.0,
                    "dates" : [ 
                        ISODate("2015-01-01T00:00:00.000Z"), 
                        ISODate("2015-01-02T00:00:00.000Z"), 
                        ISODate("2015-01-03T00:00:00.000Z")
                    ]
                }
            ]
        }
    ]
}