Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Basic example code usage in readme #27

Open
jirikrepl opened this issue May 30, 2018 · 13 comments
Open

Basic example code usage in readme #27

jirikrepl opened this issue May 30, 2018 · 13 comments

Comments

@jirikrepl
Copy link

jirikrepl commented May 30, 2018

Hi I am struggling to get this package working. Seems to me that I have connection to mongo db setup properly, because I could list my collections names from calling db._getCollectionNames

but I am not able to figure out how to get collection, so I can perform update on collection:

exports.up = function (db) {
    // how to use db to get to collection?
    // this won't work
    db.collection('Profile').update({},
        { $set: { "termsOfServiceUpdated": true } },
        {
            upsert: false,
            multi: true
        });
};

thank you very much


Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.

@wzrdtales
Copy link
Member

This is a migration library, not just a wrapper for the driver below. So you first need to access the driver should you want to perform operations not, yet, directly supported by the driver or the framework.

In case of mongodb this is getDbInstance merged from this PR over here #21

@sidharthnayyar
Copy link

Hi, sorry new to this but trying to use getDbInstance, would this be a case of just doing

exports.up = function(db, callback) {
    db.getDbInstance().getCollection(....)....
}

Thanks in advance.

Kind regards
Sidharth

@jugaltheshah
Copy link

Hi, sorry new to this but trying to use getDbInstance, would this be a case of just doing

exports.up = function(db, callback) {
    db.getDbInstance().getCollection(....)....
}

Thanks in advance.

Kind regards
Sidharth

@sidharthnayyar were you able to get db.getDbInstance() working? When I try to run it I get [ERROR] TypeError: db.getDbInstance is not a function. I confirmed I have [email protected] too.

@danielabar
Copy link

I also got db.getDbInstance is not a function. Stacktrace was from db-migrate, maybe the db object in exports.up and exports.down only has available functions from db-migrate (createCollection, dropCollection, addIndex etc.).

But debugging db, was able to get this working:

exports.up = function(db) {
  let mClient;
  return db.connection.connect(db.connectionString, { native_parser: true })
    .then((mClientInst) => {
      // mClientInst is an instance of MongoClient
      mClient = mClientInst;
      return mClient.collection('myCollection')...;
    })
    .then(() => mClient.close())
    .catch(() => mClient.close());
};

Migrations can be debugged with VS Code by adding the following to launch.json, then put a breakpoint in any up/down function:

"configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "DB Migrate Down",
      "program": "${workspaceFolder}/node_modules/.bin/db-migrate",
      "args": [
        "down"
      ]
    },
    {
      "type": "node",
      "request": "launch",
      "name": "DB Migrate Up",
      "program": "${workspaceFolder}/node_modules/.bin/db-migrate",
      "args": [
        "up"
      ]
    },
    ...
  ]
}

@jugaltheshah
Copy link

jugaltheshah commented Sep 19, 2018

Thanks for sharing your trick to getting an instance of Mongo client, @danielabar. It seems like it would open 2 connections to the db though? Thanks also for the debugging tip, that is super useful!

Actually after I posted I found this on the web, so here's what I have for now:

const collections = [{
    name: 'users'
}];

exports.down = async (db) => {
    const dbDriver = await db._run('getDbInstance');
    collections.forEach(async (collection) => {
        const fileName = collection.dataFile || `${collection.name}.json`;
        const data = require(Path.join(__dirname, 'docs', fileName));

        await Promise.all(data.map((doc) => {
            return dbDriver.collection(collection.name).deleteOne({ _id: doc._id });
        }));
    });

    dbDriver.close();
};

I wonder if there's a better way than both of ours though -- it seems risky resorting to using undocumented methods that may change internally.

@danielabar
Copy link

danielabar commented Sep 20, 2018

I see what you mean about connecting twice. Also good point about undocumented methods.

To project maintainers: Any thoughts on this - what's the recommended way to get access to mongo instance, given that getDBInstance method from PR #21 isn't working (or not sure on correct usage)?

@rymut
Copy link

rymut commented Nov 25, 2018

The problem is how the db-migrate reduce driver object to the interface db-migrate/lib/migrator.js:51-52

var Migrator = function (driver, migrationsDir, empty, intern) {
  this.driver = dbmUtil.reduceToInterface(driver, MigratorInterface);

Function reduceToInterface will remove all methods that fall outside the interface, but there is a simple solution - modify the extending object exported by adding empty method getDbInstance in db-migrate\lib\interface\migratorInterface.js module. It can be done by using db-migrate programable API (file db-migrate.js):

const MigratorInterface = require('db-migrate/lib/interface/migratorInterface');

const dummy = () => undefined;
MigratorInterface.extending.getDbInstance = dummy;

const DbMigrate = require('db-migrate');

const dbmigrate = DbMigrate.getInstance();
if (dbmigrate.registerAPIHook) {
  dbmigrate.registerAPIHook()
    .then(() => {
      dbmigrate.run();
    });
} else { dbmigrate.run(); }

Now node db-migrate should be called instead of node_modules/.bin/db-migrate and this way getDbInstance is available to use in migrations scripts.

@gmahe
Copy link

gmahe commented Jun 21, 2019

This will help people who are still looking for it:

exports.up = function(db) {
  return db._run("update", "collectionToUpdate", {
    query: { id: "1123" }, // What you need to find
    update: { title: "myNewTitle", desc: "It works" }, // What you need to change
    options: {}, // Options like e.g: upsert: false,
  });
};

Have a look here
There is also updateMany

@wzrdtales
Copy link
Member

please be aware _ methods are private and subject to change at any time without warning. they may completely change their behavior or suddenly disappear. you can use them, but be prepared that you might have to change your migrations or fixate a driver version.

@gmahe
Copy link

gmahe commented Jun 25, 2019

Is there any other way?

@dprentis
Copy link

Hello, I've been using db-migrate with mysql and it's working fine.
Now I wanted to use db-migrate with mongodb and am having trouble implementing a migration.

The only documentation I found is here:
https://db-migrate.readthedocs.io/en/latest/API/NoSQL/
It would imply there is no officially supported way of updating or deleting records - or am I missing something?

Thanks for any answer - I'll try using @jugaltheshah suggested method for now.

@gmahe
Copy link

gmahe commented Jul 16, 2019

Not the official way but you can use the bellow code to remove a single entry:

exports.down = function(db, callback) {
  db._run("remove", "pages", { id: "5bb9e79df82c0151fc0cdab2" }, callback);
};

But the code has a bug with deleteMany at the moment so you can use @jugaltheshah method.

exports.down = async function(db) {
  // Remove them all. (bug in their method at the moment)
  const getDbInstance = await db._run("getDbInstance");
  getDbInstance.collection("pets").deleteMany({ type: "cat" }); // Removes all occurrence of that value.
  getDbInstance.close();
};

More details here: https://github.com/db-migrate/mongodb/blob/master/index.js#L337

@dprentis
Copy link

thanks - I'm doing that and its working fine 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants