Open jirikrepl opened 6 years ago
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 https://github.com/db-migrate/mongodb/pull/21
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
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 db-migrate-mongodb@1.4.0 too.
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"
]
},
...
]
}
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.
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)?
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.
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
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.
Is there any other way?
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.
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
thanks - I'm doing that and its working fine 👍
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:
thank you very much