简体   繁体   中英

MongoDB Nested Documents Aggregation using Change Events

The problem is that when I push a new document inside the array field it becomes a dotted notation.

What I am trying to achieve is to filter the the response of the Change Event or the Collection.watch().

这是好的版本

But this happens

在此处输入图像描述

There is no way that I can access the updateDescription.updatedFields.message because it became a dot notation.

I tried to use

var filter = [{
    $match: {
        $and: [
            { 'documentKey._id': req.body.id },
            {'updateDescription.updatedFields.message': // value of current length of the messages array}
        ]
    }
  }];

and

var filter = [{
    $match: {
        $and: [
            { 'documentKey._id': req.body.id },
            {'updateDescription.updatedFields.messages' : {$exists: true}}
        ]
    }
  }];

I also used projection:

try{
    res.status(200).set({
      "connection":"keep-alive",
      "cache-control": "no-cache",
      "content-type":"application/json"
    });
  var query = await User.findOne({'_id': req.body.id});
  var len = parseInt(query['messages'].length);
  var _str = 'messages.'+String(len);
  console.log(_str)
  var project = [{$project: {'updateDescription.updatedFields' : {$objectToArray: '$updateDescription.updatedFields'}}}]
  var filter = [{
    $match: {
        $and: [
            { 'documentKey._id': req.body.id },
            {'updateDescription.updatedFields.k': _str}
        ]
    }
  }];

  await User.watch(filter, project).on('change', data => console.log(data))

  }catch(err){
    res.status(500).send(err);
  }

But still I haven't got any solution how to solve this.

The problem is that you are projecting it wrong.

$project: {'updateDescription.updatedFields' : {$objectToArray: '$updateDescription.updatedFields'}}

is should be

{$project: { 'updateDescription.updatedFields' : {$objectToArray: '$updateDescription.updatedFields'}, 'documentKey._id': req.body.id  }}

Then you go use regex on the $match

{$match: {
    $and: [
       { 'documentKey._id': req.body.id },
       {'updateDescription.updatedFields.k': {$regex:"^matches"}}
   ]}

Here's the full working snippet:

  try{
    res.status(200).set({
      "connection":"keep-alive",
      "cache-control": "no-cache",
      "content-type":"application/json"
    });

  var filter = [
    {$project: { 'updateDescription.updatedFields' : {$objectToArray: '$updateDescription.updatedFields'}, 'documentKey._id': req.body.id  }},
    {$match: {
        $and: [
            { 'documentKey._id': req.body.id },
            {'updateDescription.updatedFields.k': {$regex:"^matches"}}
        ]
    }
  }];

  await User.watch(filter).on('change', data => console.log(data.updateDescription.updatedFields))

  }catch(err){
    res.status(500).send(err);
  }

The reason why it's not matching is because you are using $and operator and there's no "documentKey._id" to match with since you projected it wrong.

The $filter and $project stages should be together in a single array. The watch function takes (Pipeline Array, Options Object). Try:

  var filter = [
    {$project: {'updateDescription.updatedFields' : {$objectToArray: '$updateDescription.updatedFields'}}},
    {$match: {
        $and: [
            { 'documentKey._id': req.body.id },
            {'updateDescription.updatedFields.k': _str}
        ]
    }
  }];

await User.watch(filter).on('change', data => console.log(data))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM