lucid-mongo
lucid-mongo copied to clipboard
Adonis mysql overwritten by lucid-mongo
When i add provider into app.js its overriding mysql.
I wanted to use both mysql and mongo in my application Please can any one help me?
I have the same issue. Is the only way to dot his standalone?
Same issue.
Hi ,
I have same issue, any one solve this issue.
Hi,@vshreyas-tricog @jakesyl @twigs67 @sbala69gmail I have Solved this problem. You have to modify lucid-mongo's Database configurations. You can use knex while your connection client is mysql
Replace content of '@node_modules/lucid-mongo/src/Database/index.js' with the following code.
/**
* adonis-lucid
*
* (c) Harminder Virk <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
const { MongoClient } = require('mongodb')
const mquery = require('mquery')
const CE = require('../Exceptions')
const util = require('../../lib/util')
const _ = require('lodash')
const mongoUriBuilder = require('mongo-uri-builder')
const mongoUrl = require('mongodb-url')
// const debug = require('debug')('mquery')
const knex = require('knex')
const KnexFormatter = require('knex/lib/formatter')
KnexFormatter.prototype.compileCallback = function (callback, method) {
/**
* subQuery is set by Lucid model query builder, since that querybuilder
* has more methods then a regular query builder.
*/
const builder = typeof (this.builder.subQuery) === 'function'
? this.builder.subQuery()
: this.client.queryBuilder()
/**
* All this code is a copy/paste from Knex
*/
callback.call(builder, builder)
const compiler = this.client.queryCompiler(builder)
compiler.formatter = this
return compiler.toSQL(method || builder._method || 'select')
}
const proxyHandler = {
get (target, name) {
if (typeof (name) === 'symbol' || name === 'inspect') {
return target[name]
}
if (typeof (target[name]) !== 'undefined') {
return target[name]
}
const queryBuilder = target.query()
if (typeof (queryBuilder[name]) !== 'function') {
throw new Error(`Database.${name} is not a function`)
}
/**
* Attach transacting to all the database
* queries if global transactions are on
*/
if (target._globalTrx) {
queryBuilder.transacting(target._globalTrx)
}
return queryBuilder[name].bind(queryBuilder)
}
}
class SchemaBuilder {
constructor (collection) {
this.collection = collection
this.createIndexes = []
this.dropIndexes = []
this.increments = () => this
this.timestamps = () => this
this.softDeletes = () => this
this.string = () => this
this.timestamp = () => this
this.boolean = () => this
this.integer = () => this
this.double = () => this
this.nullable = () => this
this.defaultTo = () => this
this.unsigned = () => this
this.references = () => this
}
index (name, keys, options) {
if (!name) {
throw new CE.InvalidArgumentException(`param name is required to create index`)
}
if (!keys || !_.size(keys)) {
throw new CE.InvalidArgumentException(`param keys is required to create index`)
}
options = options || {}
options['name'] = name
this.createIndexes.push({ keys, options })
}
dropIndex (name) {
this.dropIndexes.push(name)
}
async build () {
for (var i in this.createIndexes) {
var createIndex = this.createIndexes[i]
await this.collection.createIndex(createIndex.keys, createIndex.options)
}
for (var j in this.dropIndexes) {
var dropIndex = this.dropIndexes[j]
await this.collection.dropIndex(dropIndex)
}
}
}
/**
* The database class is a reference to mquery for a single
* connection. It has couple of extra methods over mquery.
*
* Note: You don't instantiate this class directly but instead
* make use of @ref('DatabaseManager')
*
* @class Database
* @constructor
* @group Database
*/
class Database {
constructor (config) {
if (config.client !== 'mongodb') {
this.connectionClient = config.client
if (config.client === 'sqlite' || config.client === 'sqlite3') {
config.useNullAsDefault = _.defaultTo(config.useNullAsDefault, true)
}
this.knex = knex(config)
this._globalTrx = null
return new Proxy(this, proxyHandler)
}
if (config.connectionString) {
this.connectionString = config.connectionString
const parsedUri = mongoUrl(this.connectionString)
this.databaseName = parsedUri.dbName || config.connection.database
} else {
this.connectionString = mongoUriBuilder(config.connection)
this.databaseName = config.connection.database
}
this.connectionOptions = _.assign({
useNewUrlParser: true
}, config.connectionOptions || {})
this.connection = null
this.db = null
this._globalTrx = null
this.query()
return new Proxy(this, proxyHandler)
}
async connect (collectionName) {
if (!this.db) {
this.connection = await MongoClient.connect(this.connectionString, this.connectionOptions)
this.db = this.connection.db(this.databaseName)
}
return Promise.resolve(this.db)
}
async getCollection (collectionName) {
if (!this.db) {
this.connection = await MongoClient.connect(this.connectionString, this.connectionOptions)
this.db = this.connection.db(this.databaseName)
}
return Promise.resolve(this.db.collection(collectionName))
}
collection (collectionName) {
this.collectionName = collectionName
this.query()
return this
}
/**
* Bind listeners for database events. Which are
* `query`, `query-error`, `query-response` and
* `sql`
*
* @method on
*
* @param {Strign} event
* @param {Function} callback
*
* @chainable
*/
on (event, callback) {
this.knex.on(event, callback)
return this
}
/**
* The schema builder instance to be used
* for creating database schema.
*
* You should obtain a new schema instance for every
* database operation and should never use stale
* instances. For example
*
* @example
* ```js
* // WRONG
* const schema = Database.schema
* schema.createCollection('users')
* schema.createCollection('profiles')
* ```
*
* ```js
* // RIGHT
* Database.schema.createCollection('users')
* Database.schema.createCollection('profiles')
* ```
*
* @attribute schema
*
* @return {Object}
*/
get schema () {
if (this.connectionClient==='mysql') {
return this.knex.schema
}
return {
collection: async (collectionName, callback) => {
// debug('create collection', { collectionName })
const db = await this.connect()
const collection = await db.collection(collectionName)
const schemaBuilder = new SchemaBuilder(collection)
callback(schemaBuilder)
return schemaBuilder.build()
},
createCollection: async (collectionName, callback) => {
// debug('create collection', {collectionName})
const db = await this.connect()
const collections = await db.listCollections().toArray()
if (_.find(collections, collection => collection.name === collectionName)) {
throw new Error('already exists')
}
const collection = await db.createCollection(collectionName)
const schemaBuilder = new SchemaBuilder(collection)
callback(schemaBuilder)
return schemaBuilder.build()
},
createCollectionIfNotExists: async (collectionName, callback) => {
// debug('create collection if not exists', { collectionName })
const db = await this.connect()
const collections = await db.listCollections().toArray()
if (!_.find(collections, collection => collection.name === collectionName)) {
const collection = await db.createCollection(collectionName)
const schemaBuilder = new SchemaBuilder(collection)
callback(schemaBuilder)
return schemaBuilder.build()
}
},
dropCollection: async (collectionName) => {
// debug('drop collection', { collectionName })
const db = await this.connect()
return db.dropCollection(collectionName)
},
dropCollectionIfExists: async (collectionName) => {
// debug('drop collection if not exists', { collectionName })
const db = await this.connect()
const collections = await db.listCollections().toArray()
if (_.find(collections, collection => collection.name === collectionName)) {
return db.dropCollection(collectionName)
}
},
renameCollection: async (collectionName, target) => {
// debug('rename collection', { collectionName, target })
const db = await this.connect()
return db.collection(collectionName).rename(target)
},
hasCollection: async (collectionName) => {
const db = await this.connect()
const collections = await db.listCollections().toArray()
return !!_.find(collections, collection => collection.name === collectionName)
}
}
}
/**
* sort
*
* @param {any} arg
* @returns
* @memberof Database
*/
sort (...arg) {
this.queryBuilder.sort(...arg)
return this
}
/**
* limit
*
* @param {any} arg
* @returns
* @memberof Database
*/
limit (...arg) {
this.queryBuilder.limit(...arg)
return this
}
/**
* where
*
* @param {any} arg
* @returns
* @memberof Database
*/
skip (...arg) {
this.queryBuilder.skip(...arg)
return this
}
/**
* select
*
* @param {any} arg
* @returns
* @memberof Database
*/
select (...arg) {
this.queryBuilder.select(...arg)
return this
}
/**
* Return a new instance of query builder
*
* @method query
*
* @return {Object}
*/
query () {
if (this.connectionClient==='mysql') {
return this.knex.queryBuilder()
}
this.queryBuilder = mquery()
this.replaceMethods()
return this.queryBuilder
}
/**
* fn
*
* @method fn
*
* @return {Object}
*/
get fn () {
if (this.connectionClient==='mysql') {
return this.knex.fn
}
return {
remove: (path) => console.log('remove', path),
now: () => new Date()
}
}
/**
* get Conditions
*
* @readonly
* @memberof Database
*/
get conditions () {
return this.queryBuilder._conditions
}
/**
* Clone
*
* @memberof Database
*/
clone () {
return _.cloneDeep(this.queryBuilder)
}
/**
* Closes the database connection. No more queries
* can be made after this.
*
* @method close
*
* @return {Promise}
*/
close () {
if (this.connectionClient==='mysql') {
return this.knex.destroy()
}
return this.connection.close()
}
/**
* Return a collection
*
* @method find
*
* @return {Object}
*/
async find () {
const connection = await this.connect()
const collection = connection.collection(this.collectionName)
return this.queryBuilder.collection(collection).find()
}
/**
* Return a document
*
* @method findOne
*
* @return {Object}
*/
async findOne () {
const connection = await this.connect()
const collection = connection.collection(this.collectionName)
return this.queryBuilder.collection(collection).findOne()
}
/**
* Return a document
*
* @method first
*
* @return {Object}
*/
async first () {
return this.findOne()
}
/**
* Return a document
*
* @method pluck
*
* @return {Object}
*/
async pluck (field) {
this.queryBuilder.select(field)
const result = await this.find()
return _.map(result, field)
}
/**
* Update collections
*
* @method update
*
* @return {Object}
*/
async update () {
const connection = await this.connect()
const collection = connection.collection(this.collectionName)
return this.queryBuilder.collection(collection).update(...arguments)
}
/**
* Remove collections
*
* @method delete
*
* @return {Object}
*/
async delete () {
const connection = await this.connect()
const collection = connection.collection(this.collectionName)
return this.queryBuilder.collection(collection).remove(...arguments)
}
/**
* Query pagination
*
* @method paginate
*
* @return {Object}
*/
async paginate (page, limit) {
const connection = await this.connect()
const collection = connection.collection(this.collectionName)
const countByQuery = await this.aggregate('count')
const rows = await this.queryBuilder.collection(collection).limit(limit).skip((page || 1) * limit).find()
const result = util.makePaginateMeta(countByQuery || 0, page, limit)
result.data = rows
return result
}
/**
* Insert document
*
* @method insert
*
* @return {Object}
*/
async insert (row) {
const connection = await this.connect()
const collection = connection.collection(this.collectionName)
return collection.insert(row)
}
/**
* @method count
*
* @param {any} args
* @returns {Number|Array}
* @memberof Database
*/
count (...args) {
return this.aggregate('count', null, ...args)
}
/**
* @method count
*
* @param {any} args
* @returns {Number|Array}
* @memberof Database
*/
sum (...args) {
return this.aggregate('sum', ...args)
}
/**
* @method count
*
* @param {any} args
* @returns {Number|Array}
* @memberof Database
*/
avg (...args) {
return this.aggregate('avg', ...args)
}
/**
* @method count
*
* @param {any} args
* @returns {Number|Array}
* @memberof Database
*/
max (...args) {
return this.aggregate('max', ...args)
}
/**
* @method count
*
* @param {any} args
* @returns {Number|Array}
* @memberof Database
*/
min (...args) {
return this.aggregate('min', ...args)
}
/**
* Aggregation
*
* @method aggregate
*
* @return {Object}
*/
async aggregate (aggregator, key, groupBy) {
const $match = this.conditions
const $group = { _id: '$' + groupBy }
switch (aggregator) {
case 'count':
$group[aggregator] = { $sum: 1 }
break
case 'max':
$group[aggregator] = { $max: '$' + key }
break
case 'min':
$group[aggregator] = { $min: '$' + key }
break
case 'sum':
$group[aggregator] = { $sum: '$' + key }
break
case 'avg':
$group[aggregator] = { $avg: '$' + key }
break
default:
break
}
// debug('count', this.collectionName, $match, $group)
const connection = await this.connect()
const collection = connection.collection(this.collectionName)
const result = await collection.aggregate([{ $match }, { $group }]).toArray()
return groupBy ? result : !_.isEmpty(result) ? result[0][aggregator] : null
}
/**
* Query distinct
*
* @method distinct
*
* @return {Object}
*/
async distinct () {
const connection = await this.connect()
const collection = connection.collection(this.collectionName)
return this.queryBuilder.collection(collection).distinct(...arguments)
}
/**
* Condition Methods
*
* @readonly
* @static
* @memberof QueryBuilder
*/
static get conditionMethods () {
return [
'eq',
'ne',
'gt',
'gte',
'lt',
'lte',
'in',
'nin',
'all',
'near',
'maxDistance',
'mod',
'includes',
'polygon',
'elemMatch',
'geometry',
'intersects'
]
}
/**
* replace condition methods of mquery
*
* @memberof QueryBuilder
*/
replaceMethods () {
for (let name of this.constructor.conditionMethods) {
let originMethod = this.queryBuilder[name]
this.queryBuilder[name] = (param) => {
originMethod.apply(this.queryBuilder, [param])
return this
}
}
}
/**
* Replace where method
*
* @returns {this}
* @memberof QueryBuilder
*/
where () {
if (arguments.length === 3) {
switch (arguments[1]) {
case '=':
this.queryBuilder.where(arguments[0]).eq(arguments[2])
break
case '>':
this.queryBuilder.where(arguments[0]).gt(arguments[2])
break
case '>=':
this.queryBuilder.where(arguments[0]).gte(arguments[2])
break
case '<':
this.queryBuilder.where(arguments[0]).lt(arguments[2])
break
case '<=':
this.queryBuilder.where(arguments[0]).lte(arguments[2])
break
case '<>':
this.queryBuilder.where(arguments[0]).ne(arguments[2])
break
default:
throw new CE.InvalidArgumentException(`Method "$${arguments[1]}" is not support by query builder`)
}
} else if (arguments.length === 2 || _.isPlainObject(arguments[0])) {
this.queryBuilder.where(...arguments)
} else {
return this.queryBuilder.where(...arguments)
}
return this
}
/**
* Method to construct raw database queries.
*
* @method raw
*
* @param {...Spread} args
*
* @return {String}
*/
raw (...args) {
return this._globalTrx ? this._globalTrx.raw(...args) : this.knex.raw(...args)
}
/**
* Returns a trx object to be used for running queries
* under transaction.
*
* @method beginTransaction
* @async
*
* @return {Object}
*
* @example
* ```js
* const trx = await Database.beginTransaction()
* await trx
* .table('users')
* .insert({ username: 'virk' })
*
* // or
* Database
* .table('users')
* .transacting(trx)
* .insert({ username: 'virk' })
* ```
*/
beginTransaction () {
return new Promise((resolve, reject) => {
this
.knex
.transaction(function (trx) {
resolve(trx)
}).catch(() => {})
})
}
/**
* Run a callback inside a transaction
*
* @param {Function} callback
*
* @method transaction
*
* @returns Object
*/
transaction (callback) {
return this.knex.transaction(callback)
}
/**
* Starts a global transaction, where all query builder
* methods will be part of transaction automatically.
*
* Note: You must not use it in real world apart from when
* writing tests.
*
* @method beginGlobalTransaction
* @async
*
* @return {void}
*/
async beginGlobalTransaction () {
this._globalTrx = await this.beginTransaction()
}
/**
* Rollbacks global transaction.
*
* @method rollbackGlobalTransaction
*
* @return {void}
*/
async rollbackGlobalTransaction () {
await this._globalTrx.rollback()
this._globalTrx = null
}
/**
* Commits global transaction.
*
* @method commitGlobalTransaction
*
* @return {void}
*/
async commitGlobalTransaction () {
await this._globalTrx.commit()
this._globalTrx = null
}
}
module.exports = Database
Hi,@vshreyas-tricog @jakesyl @twigs67 @sbala69gmail I have Solved this problem. You have to modify lucid-mongo's Database configurations. You can use knex while your connection client is mysql
Replace content of '@node_modules/lucid-mongo/src/Database/index.js' with the following code.
/** * adonis-lucid * * (c) Harminder Virk <[email protected]> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ const { MongoClient } = require('mongodb') const mquery = require('mquery') const CE = require('../Exceptions') const util = require('../../lib/util') const _ = require('lodash') const mongoUriBuilder = require('mongo-uri-builder') const mongoUrl = require('mongodb-url') // const debug = require('debug')('mquery') const knex = require('knex') const KnexFormatter = require('knex/lib/formatter') KnexFormatter.prototype.compileCallback = function (callback, method) { /** * subQuery is set by Lucid model query builder, since that querybuilder * has more methods then a regular query builder. */ const builder = typeof (this.builder.subQuery) === 'function' ? this.builder.subQuery() : this.client.queryBuilder() /** * All this code is a copy/paste from Knex */ callback.call(builder, builder) const compiler = this.client.queryCompiler(builder) compiler.formatter = this return compiler.toSQL(method || builder._method || 'select') } const proxyHandler = { get (target, name) { if (typeof (name) === 'symbol' || name === 'inspect') { return target[name] } if (typeof (target[name]) !== 'undefined') { return target[name] } const queryBuilder = target.query() if (typeof (queryBuilder[name]) !== 'function') { throw new Error(`Database.${name} is not a function`) } /** * Attach transacting to all the database * queries if global transactions are on */ if (target._globalTrx) { queryBuilder.transacting(target._globalTrx) } return queryBuilder[name].bind(queryBuilder) } } class SchemaBuilder { constructor (collection) { this.collection = collection this.createIndexes = [] this.dropIndexes = [] this.increments = () => this this.timestamps = () => this this.softDeletes = () => this this.string = () => this this.timestamp = () => this this.boolean = () => this this.integer = () => this this.double = () => this this.nullable = () => this this.defaultTo = () => this this.unsigned = () => this this.references = () => this } index (name, keys, options) { if (!name) { throw new CE.InvalidArgumentException(`param name is required to create index`) } if (!keys || !_.size(keys)) { throw new CE.InvalidArgumentException(`param keys is required to create index`) } options = options || {} options['name'] = name this.createIndexes.push({ keys, options }) } dropIndex (name) { this.dropIndexes.push(name) } async build () { for (var i in this.createIndexes) { var createIndex = this.createIndexes[i] await this.collection.createIndex(createIndex.keys, createIndex.options) } for (var j in this.dropIndexes) { var dropIndex = this.dropIndexes[j] await this.collection.dropIndex(dropIndex) } } } /** * The database class is a reference to mquery for a single * connection. It has couple of extra methods over mquery. * * Note: You don't instantiate this class directly but instead * make use of @ref('DatabaseManager') * * @class Database * @constructor * @group Database */ class Database { constructor (config) { if (config.client !== 'mongodb') { this.connectionClient = config.client if (config.client === 'sqlite' || config.client === 'sqlite3') { config.useNullAsDefault = _.defaultTo(config.useNullAsDefault, true) } this.knex = knex(config) this._globalTrx = null return new Proxy(this, proxyHandler) } if (config.connectionString) { this.connectionString = config.connectionString const parsedUri = mongoUrl(this.connectionString) this.databaseName = parsedUri.dbName || config.connection.database } else { this.connectionString = mongoUriBuilder(config.connection) this.databaseName = config.connection.database } this.connectionOptions = _.assign({ useNewUrlParser: true }, config.connectionOptions || {}) this.connection = null this.db = null this._globalTrx = null this.query() return new Proxy(this, proxyHandler) } async connect (collectionName) { if (!this.db) { this.connection = await MongoClient.connect(this.connectionString, this.connectionOptions) this.db = this.connection.db(this.databaseName) } return Promise.resolve(this.db) } async getCollection (collectionName) { if (!this.db) { this.connection = await MongoClient.connect(this.connectionString, this.connectionOptions) this.db = this.connection.db(this.databaseName) } return Promise.resolve(this.db.collection(collectionName)) } collection (collectionName) { this.collectionName = collectionName this.query() return this } /** * Bind listeners for database events. Which are * `query`, `query-error`, `query-response` and * `sql` * * @method on * * @param {Strign} event * @param {Function} callback * * @chainable */ on (event, callback) { this.knex.on(event, callback) return this } /** * The schema builder instance to be used * for creating database schema. * * You should obtain a new schema instance for every * database operation and should never use stale * instances. For example * * @example * ```js * // WRONG * const schema = Database.schema * schema.createCollection('users') * schema.createCollection('profiles') * ``` * * ```js * // RIGHT * Database.schema.createCollection('users') * Database.schema.createCollection('profiles') * ``` * * @attribute schema * * @return {Object} */ get schema () { if (this.connectionClient==='mysql') { return this.knex.schema } return { collection: async (collectionName, callback) => { // debug('create collection', { collectionName }) const db = await this.connect() const collection = await db.collection(collectionName) const schemaBuilder = new SchemaBuilder(collection) callback(schemaBuilder) return schemaBuilder.build() }, createCollection: async (collectionName, callback) => { // debug('create collection', {collectionName}) const db = await this.connect() const collections = await db.listCollections().toArray() if (_.find(collections, collection => collection.name === collectionName)) { throw new Error('already exists') } const collection = await db.createCollection(collectionName) const schemaBuilder = new SchemaBuilder(collection) callback(schemaBuilder) return schemaBuilder.build() }, createCollectionIfNotExists: async (collectionName, callback) => { // debug('create collection if not exists', { collectionName }) const db = await this.connect() const collections = await db.listCollections().toArray() if (!_.find(collections, collection => collection.name === collectionName)) { const collection = await db.createCollection(collectionName) const schemaBuilder = new SchemaBuilder(collection) callback(schemaBuilder) return schemaBuilder.build() } }, dropCollection: async (collectionName) => { // debug('drop collection', { collectionName }) const db = await this.connect() return db.dropCollection(collectionName) }, dropCollectionIfExists: async (collectionName) => { // debug('drop collection if not exists', { collectionName }) const db = await this.connect() const collections = await db.listCollections().toArray() if (_.find(collections, collection => collection.name === collectionName)) { return db.dropCollection(collectionName) } }, renameCollection: async (collectionName, target) => { // debug('rename collection', { collectionName, target }) const db = await this.connect() return db.collection(collectionName).rename(target) }, hasCollection: async (collectionName) => { const db = await this.connect() const collections = await db.listCollections().toArray() return !!_.find(collections, collection => collection.name === collectionName) } } } /** * sort * * @param {any} arg * @returns * @memberof Database */ sort (...arg) { this.queryBuilder.sort(...arg) return this } /** * limit * * @param {any} arg * @returns * @memberof Database */ limit (...arg) { this.queryBuilder.limit(...arg) return this } /** * where * * @param {any} arg * @returns * @memberof Database */ skip (...arg) { this.queryBuilder.skip(...arg) return this } /** * select * * @param {any} arg * @returns * @memberof Database */ select (...arg) { this.queryBuilder.select(...arg) return this } /** * Return a new instance of query builder * * @method query * * @return {Object} */ query () { if (this.connectionClient==='mysql') { return this.knex.queryBuilder() } this.queryBuilder = mquery() this.replaceMethods() return this.queryBuilder } /** * fn * * @method fn * * @return {Object} */ get fn () { if (this.connectionClient==='mysql') { return this.knex.fn } return { remove: (path) => console.log('remove', path), now: () => new Date() } } /** * get Conditions * * @readonly * @memberof Database */ get conditions () { return this.queryBuilder._conditions } /** * Clone * * @memberof Database */ clone () { return _.cloneDeep(this.queryBuilder) } /** * Closes the database connection. No more queries * can be made after this. * * @method close * * @return {Promise} */ close () { if (this.connectionClient==='mysql') { return this.knex.destroy() } return this.connection.close() } /** * Return a collection * * @method find * * @return {Object} */ async find () { const connection = await this.connect() const collection = connection.collection(this.collectionName) return this.queryBuilder.collection(collection).find() } /** * Return a document * * @method findOne * * @return {Object} */ async findOne () { const connection = await this.connect() const collection = connection.collection(this.collectionName) return this.queryBuilder.collection(collection).findOne() } /** * Return a document * * @method first * * @return {Object} */ async first () { return this.findOne() } /** * Return a document * * @method pluck * * @return {Object} */ async pluck (field) { this.queryBuilder.select(field) const result = await this.find() return _.map(result, field) } /** * Update collections * * @method update * * @return {Object} */ async update () { const connection = await this.connect() const collection = connection.collection(this.collectionName) return this.queryBuilder.collection(collection).update(...arguments) } /** * Remove collections * * @method delete * * @return {Object} */ async delete () { const connection = await this.connect() const collection = connection.collection(this.collectionName) return this.queryBuilder.collection(collection).remove(...arguments) } /** * Query pagination * * @method paginate * * @return {Object} */ async paginate (page, limit) { const connection = await this.connect() const collection = connection.collection(this.collectionName) const countByQuery = await this.aggregate('count') const rows = await this.queryBuilder.collection(collection).limit(limit).skip((page || 1) * limit).find() const result = util.makePaginateMeta(countByQuery || 0, page, limit) result.data = rows return result } /** * Insert document * * @method insert * * @return {Object} */ async insert (row) { const connection = await this.connect() const collection = connection.collection(this.collectionName) return collection.insert(row) } /** * @method count * * @param {any} args * @returns {Number|Array} * @memberof Database */ count (...args) { return this.aggregate('count', null, ...args) } /** * @method count * * @param {any} args * @returns {Number|Array} * @memberof Database */ sum (...args) { return this.aggregate('sum', ...args) } /** * @method count * * @param {any} args * @returns {Number|Array} * @memberof Database */ avg (...args) { return this.aggregate('avg', ...args) } /** * @method count * * @param {any} args * @returns {Number|Array} * @memberof Database */ max (...args) { return this.aggregate('max', ...args) } /** * @method count * * @param {any} args * @returns {Number|Array} * @memberof Database */ min (...args) { return this.aggregate('min', ...args) } /** * Aggregation * * @method aggregate * * @return {Object} */ async aggregate (aggregator, key, groupBy) { const $match = this.conditions const $group = { _id: '$' + groupBy } switch (aggregator) { case 'count': $group[aggregator] = { $sum: 1 } break case 'max': $group[aggregator] = { $max: '$' + key } break case 'min': $group[aggregator] = { $min: '$' + key } break case 'sum': $group[aggregator] = { $sum: '$' + key } break case 'avg': $group[aggregator] = { $avg: '$' + key } break default: break } // debug('count', this.collectionName, $match, $group) const connection = await this.connect() const collection = connection.collection(this.collectionName) const result = await collection.aggregate([{ $match }, { $group }]).toArray() return groupBy ? result : !_.isEmpty(result) ? result[0][aggregator] : null } /** * Query distinct * * @method distinct * * @return {Object} */ async distinct () { const connection = await this.connect() const collection = connection.collection(this.collectionName) return this.queryBuilder.collection(collection).distinct(...arguments) } /** * Condition Methods * * @readonly * @static * @memberof QueryBuilder */ static get conditionMethods () { return [ 'eq', 'ne', 'gt', 'gte', 'lt', 'lte', 'in', 'nin', 'all', 'near', 'maxDistance', 'mod', 'includes', 'polygon', 'elemMatch', 'geometry', 'intersects' ] } /** * replace condition methods of mquery * * @memberof QueryBuilder */ replaceMethods () { for (let name of this.constructor.conditionMethods) { let originMethod = this.queryBuilder[name] this.queryBuilder[name] = (param) => { originMethod.apply(this.queryBuilder, [param]) return this } } } /** * Replace where method * * @returns {this} * @memberof QueryBuilder */ where () { if (arguments.length === 3) { switch (arguments[1]) { case '=': this.queryBuilder.where(arguments[0]).eq(arguments[2]) break case '>': this.queryBuilder.where(arguments[0]).gt(arguments[2]) break case '>=': this.queryBuilder.where(arguments[0]).gte(arguments[2]) break case '<': this.queryBuilder.where(arguments[0]).lt(arguments[2]) break case '<=': this.queryBuilder.where(arguments[0]).lte(arguments[2]) break case '<>': this.queryBuilder.where(arguments[0]).ne(arguments[2]) break default: throw new CE.InvalidArgumentException(`Method "$${arguments[1]}" is not support by query builder`) } } else if (arguments.length === 2 || _.isPlainObject(arguments[0])) { this.queryBuilder.where(...arguments) } else { return this.queryBuilder.where(...arguments) } return this } /** * Method to construct raw database queries. * * @method raw * * @param {...Spread} args * * @return {String} */ raw (...args) { return this._globalTrx ? this._globalTrx.raw(...args) : this.knex.raw(...args) } /** * Returns a trx object to be used for running queries * under transaction. * * @method beginTransaction * @async * * @return {Object} * * @example * ```js * const trx = await Database.beginTransaction() * await trx * .table('users') * .insert({ username: 'virk' }) * * // or * Database * .table('users') * .transacting(trx) * .insert({ username: 'virk' }) * ``` */ beginTransaction () { return new Promise((resolve, reject) => { this .knex .transaction(function (trx) { resolve(trx) }).catch(() => {}) }) } /** * Run a callback inside a transaction * * @param {Function} callback * * @method transaction * * @returns Object */ transaction (callback) { return this.knex.transaction(callback) } /** * Starts a global transaction, where all query builder * methods will be part of transaction automatically. * * Note: You must not use it in real world apart from when * writing tests. * * @method beginGlobalTransaction * @async * * @return {void} */ async beginGlobalTransaction () { this._globalTrx = await this.beginTransaction() } /** * Rollbacks global transaction. * * @method rollbackGlobalTransaction * * @return {void} */ async rollbackGlobalTransaction () { await this._globalTrx.rollback() this._globalTrx = null } /** * Commits global transaction. * * @method commitGlobalTransaction * * @return {void} */ async commitGlobalTransaction () { await this._globalTrx.commit() this._globalTrx = null } } module.exports = Database
Is this solution still working?
Is this solution still working?
I recently stumbled across this same issue and I didn't want to mess around with the code in the node_modules directory and also I wasn't comfortable with using none certified code without a guarantee of not having internal issues with the framework's proprietary code. Hence, I got messing around with the start/app.js file and I discovered that if you switch or remove any one of the providers you will be able to use one of the databases as the primary database for the framework. So in this case, if you are trying to use the mysql database as the primary database for migrations then you will have to place the lucid-mongo providers before the internal frameworks providers. For example; Switch this
const providers = [
'@adonisjs/framework/providers/AppProvider',
'@adonisjs/framework/providers/ViewProvider',
'@adonisjs/bodyparser/providers/BodyParserProvider',
'@adonisjs/cors/providers/CorsProvider',
'@adonisjs/shield/providers/ShieldProvider',
'@adonisjs/session/providers/SessionProvider',
'@adonisjs/lucid/providers/LucidProvider',
'@adonisjs/auth/providers/AuthProvider',
'lucid-mongo/providers/LucidMongoProvider'
]
const aceProviders = [
'@adonisjs/lucid/providers/MigrationsProvider',
'lucid-mongo/providers/MigrationsProvider'
]
to this
`const providers = [
'@adonisjs/framework/providers/AppProvider',
'@adonisjs/framework/providers/ViewProvider',
'@adonisjs/bodyparser/providers/BodyParserProvider',
'@adonisjs/cors/providers/CorsProvider',
'@adonisjs/shield/providers/ShieldProvider',
'@adonisjs/session/providers/SessionProvider',
'@adonisjs/auth/providers/AuthProvider',
'lucid-mongo/providers/LucidMongoProvider',
'@adonisjs/lucid/providers/LucidProvider'
]
const aceProviders = [
'lucid-mongo/providers/MigrationsProvider',
'@adonisjs/lucid/providers/MigrationsProvider'
]`
And everything should go back to normal, that's if were talking about the same issue here!
Likewise, I'm guessing if you will want to use the lucid-mongo ORM at the same time with the internal framework's lucid ORM then, you may have to find a way of extending the lucid-mongo Model instead of the one that comes out of the box. But if you are looking for a sort of Hybrid relationship between the mysql and mongo DB then in this case I am assuming you are out of luck on this one, because, I am guessing the framework was not designed to handle that kind of thing, which in my own opinion, is a really great feature that the framework is missing, and this drawback is making me to reconsider my decision to use this framework.
By the way, in my own case I had run my queries by connecting directly to the mongoDB without models and relationships.
Is this solution still working?
I recently stumbled across this same issue and I didn't want to mess around with the code in the node_modules directory and also I wasn't comfortable with using none certified code without a guarantee of not having internal issues with the framework's proprietary code. Hence, I got messing around with the start/app.js file and I discovered that if you switch or remove any one of the providers you will be able to use one of the databases as the primary database for the framework. So in this case, if you are trying to use the mysql database as the primary database for migrations then you will have to place the lucid-mongo providers before the internal frameworks providers. For example; Switch this
const providers = [ '@adonisjs/framework/providers/AppProvider', '@adonisjs/framework/providers/ViewProvider', '@adonisjs/bodyparser/providers/BodyParserProvider', '@adonisjs/cors/providers/CorsProvider', '@adonisjs/shield/providers/ShieldProvider', '@adonisjs/session/providers/SessionProvider', '@adonisjs/lucid/providers/LucidProvider', '@adonisjs/auth/providers/AuthProvider', 'lucid-mongo/providers/LucidMongoProvider' ] const aceProviders = [ '@adonisjs/lucid/providers/MigrationsProvider', 'lucid-mongo/providers/MigrationsProvider' ]
to this
`const providers = [ '@adonisjs/framework/providers/AppProvider', '@adonisjs/framework/providers/ViewProvider', '@adonisjs/bodyparser/providers/BodyParserProvider', '@adonisjs/cors/providers/CorsProvider', '@adonisjs/shield/providers/ShieldProvider', '@adonisjs/session/providers/SessionProvider', '@adonisjs/auth/providers/AuthProvider', 'lucid-mongo/providers/LucidMongoProvider', '@adonisjs/lucid/providers/LucidProvider' ] const aceProviders = [ 'lucid-mongo/providers/MigrationsProvider', '@adonisjs/lucid/providers/MigrationsProvider' ]`
And everything should go back to normal, that's if were talking about the same issue here!
Likewise, I'm guessing if you will want to use the lucid-mongo ORM at the same time with the internal framework's lucid ORM then, you may have to find a way of extending the lucid-mongo Model instead of the one that comes out of the box. But if you are looking for a sort of Hybrid relationship between the mysql and mongo DB then in this case I am assuming you are out of luck on this one, because, I am guessing the framework was not designed to handle that kind of thing, which in my own opinion, is a really great feature that the framework is missing, and this drawback is making me to reconsider my decision to use this framework.
By the way, in my own case I had run my queries by connecting directly to the mongoDB without models and relationships.
So after hours of surfing the internet and playing around with the framework, I ended up with solution I posted here in the adonisjs forum