seppevs/migrate-mongo

Aggregate $out stage does not work

alexdanilowicz opened this issue · 5 comments

Describe the bug
Aggregation pipeline, $out stage does not work

To Reproduce

Steps to reproduce the behavior:

module.exports = {
  async up(db, client) {
    return await db.collection('original_collection').aggregate([
      {
        $project: {
          "hello": "world"
        },
      },
      {
        $out: 'test',
      },
    ]);
  },

  async down(db, client) {
  },
};


Expected behavior
I would expect a test collection to be created

Additional context

"migrate-mongo": "^8.2.2",
"node": "12.18.3",
"mongodb": "^3.6.6",

migrate-mongo-config.js below. Thank you! :)

// In this file you can configure migrate-mongo

const config = {
  mongodb: {
    url: process.env.mongodb,

    // TODO Change this to your database name:
    databaseName: 'database1',

    options: {
      useNewUrlParser: true, // removes a deprecation warning when connecting
      useUnifiedTopology: true, // removes a deprecating warning when connecting
      //   connectTimeoutMS: 3600000, // increase connection timeout to 1 hour
      //   socketTimeoutMS: 3600000, // increase socket timeout to 1 hour
    },
  },

  // The migrations dir, can be an relative or absolute path. Only edit this when really necessary.
  migrationsDir: 'migrations',

  // The mongodb collection where the applied changes are stored. Only edit this when really necessary.
  changelogCollectionName: 'changelog',

  // The file extension to create migrations and search for in migration dir
  migrationFileExtension: '.js',
};

// Return the config as a promise
module.exports = config;

@seppevs
I face the same problem. can you fix this issue?

@seppevs I have an issue with $merge pipeline, it won't work as it should. would you fix it or guide me to resolve this problem?

@alexdanilowicz did you find another solution that $out stage works with it?

I got it, this package use mongodb package behind the since. so when we are coding like this:

await db.collection('collection-name').aggregate([
  /* piplelines */
  {
    $merge: { // or $out
      into: 'another-collection'
    }
  }
])

we are ignoring one fact, the aggregate function does not return a promise. so we have to use .toArray() after the aggregate method (ref). so the final solution would be: await db.collection('collection-name').aggregate([/*pipelines*/]).toArray()

OK, but my problem still exists, after all of this researches and fixes, I got this error: MongoError: Unrecognized pipeline stage name: '$merge'. and I think the $merge is not supported in the MongoDB v4.0.1.

  • the $out has no problem

so what else can I do?

I got it, this package use mongodb package behind the since. so when we are coding like this:

await db.collection('collection-name').aggregate([
  /* piplelines */
  {
    $merge: { // or $out
      into: 'another-collection'
    }
  }
])

we are ignoring one fact, the aggregate function does not return a promise. so we have to use .toArray() after the aggregate method (ref). so the final solution would be: await db.collection('collection-name').aggregate([/*pipelines*/]).toArray()

OK, but my problem still exists, after all of this researches and fixes, I got this error: MongoError: Unrecognized pipeline stage name: '$merge'. and I think the $merge is not supported in the MongoDB v4.0.1.

  • the $out has no problem

so what else can I do?

Resolved, Caused by low MongoDB server version. I had v3.6.8 and after updating to v4.4.1 the problem fixed, it works fine.

@seppevs you can close this issue, it is not your library fault.

finall comment

solution

await db.collection('collection-name')
  .aggregate([
    /* piplelines */
    {
      $out: { /* your collection */ }
    }
  ])
  .toArray();

you have to call .toArray() method, because aggregate does not return promise but toArray() return a promise

@alexdanilowicz please close this issue