$ replaceRoot之后的MongoDB $匹配阶段

时间:2017-08-16 13:19:53

标签: mongodb match aggregate root reduce

请考虑以下事项。 我有文件,我保存字段的版本。 原始文档中的字段可以为null,我只保存实际更改的字段。 例如:

{
    _id : abc,
    state : 'NEW',
    field2 : 'WILL NOT CHANGE',
    field3 : null,
    lastChange : 1236547
    changes : [
      {
         state : 'WORKING',
         field3 : 'SOMETHING'
      },
      {
         state : 'DONE'
      }
    ]
}

在我的聚合管道中,我通过将所有版本与文档根合并来构建最新版本的文档。这意味着我避免了复杂的查询,我在其中搜索更改数组并找到我想要查找的每个字段的最新版本,并且我受益于管道将最新文档版本作为文档返回的副作用。下面的管道在我的问题所在的位置结束。在应用程序中,还有更多的阶段进行计数和分组等。

Mongoose: meldungs.aggregate([
{
    '$match': {
        '$and': [{
            lastChange: {
                '$ne': null
            }
        },
        {
            lastChange: {
                '$gte': ISODate('2017-03-01T23:00:00.000Z')
            }
        },
        {
            lastChange: {
                '$lt': ISODate('2017-03-02T22:59:59.999Z')
            }
        }]
    }
},
{
    '$replaceRoot': {
        newRoot: {
            '$arrayToObject': {
                '$reduce': {
                    input: '$changes',
                    initialValue: {
                        '$filter': {
                            input: {
                                '$objectToArray': '$$ROOT'
                            },
                            as: 'field',
                            cond: {
                                '$and': [
                                  { $ne : [ '$$field.v', null ] },
                                  { $ne : [ '$$field.k', '_id' ] }
                                ]
                            }
                        }
                    },
                    in: {
                        '$concatArrays': ['$$value',
                        {
                            '$filter': {
                                input: {
                                    '$objectToArray': '$$this.changes'
                                },
                                as: 'field',
                                cond: {
                                  $ne : [ '$$field.v', null ]
                                }
                            }
                        }]
                    }
                }
            }
        }
    }
},
{
  '$match': {
     state: { '$eq': 'DONE' }
  }
],
{})

这很有效,新文档看起来很正常:

{
    state : 'DONE',
    field2 : 'WILL NOT CHANGE',
    field3 : 'SOMETHING',
    lastChange : 1236547
}

我的问题是,合并/缩小之后的匹配阶段无法查询'新文件。相反,似乎使用了旧的字段值。

state: { '$eq': 'DONE' } // should return the document, but doesn't
state: { '$eq': 'NEW' } // should NOT return the document but does

我最好的猜测是,这与管道优化有关吗?意味着优化器将$ match语句移动到第一阶段,或类似的东西。 有没有人也有这个问题并且知道解决方案?

Udpate 1

经过更多测试后,似乎使用$$ ROOT作为reduce的initialValue是问题的一部分。如果我使用一个空数组作为initialValue,我可以正确匹配减少的字段。

0 个答案:

没有答案