Nodejs 有什么方法可以提供兼容mysql,mongodb 两种数据库。比如同时兼容两种数据库驱动,并且做到底层跟上层解耦。

Nodejs 有什么方法可以提供兼容mysql,mongodb 两种数据库。比如同时兼容两种数据库驱动,并且做到底层跟上层解耦。

有什么方法可以提供兼容mysql,mongodb 两种数据库。比如同时兼容两种数据库驱动,并且做到底层跟上层解耦。 我想过很多方法,但是都没法达到目的。两种数据库本身的特性根本没办法以接口解耦。除非放弃一方的特性

17 回复

Node.js 兼容 MySQL 和 MongoDB 的方法

在 Node.js 中,想要同时兼容 MySQL 和 MongoDB 并保持上层业务逻辑与底层数据访问逻辑解耦,可以通过抽象一个统一的数据访问层(DAO, Data Access Object)来实现。这样可以使得业务逻辑不依赖于具体的数据库类型,从而提高代码的可维护性和可扩展性。

示例代码

  1. 定义通用的 DAO 接口
// daoInterface.js
class DAO {
    async create(data) {
        throw new Error('Method not implemented');
    }

    async read(query) {
        throw new Error('Method not implemented');
    }

    async update(id, data) {
        throw new Error('Method not implemented');
    }

    async delete(id) {
        throw new Error('Method not implemented');
    }
}

module.exports = DAO;
  1. 实现 MySQL 的 DAO
// mysqlDAO.js
const mysql = require('mysql2/promise');

class MySQLDAO extends DAO {
    constructor(config) {
        super();
        this.pool = mysql.createPool(config);
    }

    async create(data) {
        const connection = await this.pool.getConnection();
        try {
            const [result] = await connection.query('INSERT INTO table_name SET ?', data);
            return result.insertId;
        } finally {
            connection.release();
        }
    }

    // 实现其他方法,如 read, update, delete
}

module.exports = MySQLDAO;
  1. 实现 MongoDB 的 DAO
// mongoDAO.js
const MongoClient = require('mongodb').MongoClient;

class MongoDBDAO extends DAO {
    constructor(config) {
        super();
        this.client = new MongoClient(config.url, { useNewUrlParser: true, useUnifiedTopology: true });
    }

    async create(data) {
        await this.client.connect();
        const db = this.client.db(this.client.s.options.dbName);
        const collection = db.collection('collection_name');
        const result = await collection.insertOne(data);
        return result.insertedId;
    }

    // 实现其他方法,如 read, update, delete
}

module.exports = MongoDBDAO;
  1. 使用 DAO 层
// app.js
const DAO = require('./daoInterface');
const MySQLDAO = require('./mysqlDAO');
const MongoDBDAO = require('./mongoDAO');

async function main() {
    const config = {
        host: 'localhost',
        user: 'root',
        password: 'password',
        database: 'testdb'
    };

    const mysqlDAO = new MySQLDAO(config);
    const mongoConfig = {
        url: 'mongodb://localhost:27017/testdb'
    };
    const mongoDAO = new MongoDBDAO(mongoConfig);

    // 使用 DAO 进行操作
    await mysqlDAO.create({ name: 'John Doe' });
    await mongoDAO.create({ name: 'Jane Doe' });

    console.log('Data created successfully!');
}

main().catch(console.error);

通过这种方式,你可以将业务逻辑与具体的数据库实现解耦,只需要根据需要选择不同的 DAO 实现即可。这样不仅提高了代码的灵活性,也便于未来的扩展和维护。


其实已经有相关成熟的解决方案,不过不是在nodejs平台,而是java平台。没错,就是JPA/JDO这种叫好不叫座的玩意,具体实现方案参见spring/hibernate。这类设想总是看起来很美好,实现起来很艹蛋,用起来痛不欲生。

https://github.com/meltingice/node-activerecord 这有个,SQL/NoSQL不过有一年 没更新过了,coffee源码,你可以做些参考…

我现在能想到就是在实现上解耦,针对实现写两套操作,怎对两种数据库写两种不同的数据库表结构。但是实在蛋疼。我现在最想不通就是我要针对实现,还是针对框架(就是写套框架)

刚刚又在思考框架,我都晕了,把两种驱动加进来不难,但是在语法层要实现两种数据库接口统一,尤其是调用端,根本不可能似的。

如果你说mysql或是oracle这样的同种类型的数据库(关系型),那ORM还有意义,但想构建一套对NoSQL和SQL都兼容的ORM,不说难度和复杂度,业务场景上讲也很少这种需求吧,还是各取所需的好。

主要是针对存储那边的统一接口,而非针对业务。将业务跟底层分离开。现在才发现,除非我们不仅仅定义接口实现,最重要的是定义底层数据库不同的逻辑处理。也就是说要包括其中数据库表结构的定义也要放在那里。

我是用一个模型 model 做两种表达。SQL 方面写了个引擎 - 根据模型产生 SQL 语句。

特性呢,比如addToSet 之类的针对每个的特性就表达不清了,我现在才知道要想统一只有把他们放到业务层里去,分别定义。但是……

我用geddy框架,现在的sails,waterflow等框架都能提供不同类型的model,,,我刚做了个项目,同一张表一部分数据放在mysql,另一部分数据放在mongo,用的直接驱动写两种sql语句,请大牛指正

我觉底层这种本质上的差异还是不要隐藏的好

geddy 里用的是这个 https://github.com/geddy/model ,类似 Rails 里 ActiveRecord 的 ORM,支持 MySQL、MongoDB

听我的吧,别去做什么orm , jsdo 。现在开发人谁能不会sql呢(可以吗), 你就只要写一套CURD的 dao,把Sql直接交给controller 。不要去模仿那些orm 框架了(都是坑后代),nodejs 本身语法特点就很不错,不要把nodejs也给框起来了。

有好点的处理mysql的orm ? node下的

二者根本不是一个模型的东西,sql需要设计关系模型,而nosql大多是没有模式的,所以操作很难统一,java层面我又方案,抽象一个套curd操作,node没试过!

感觉比较难,但是ORM的话有点意思

为了实现 Node.js 应用程序中对 MySQL 和 MongoDB 的兼容性,并保持上下层的解耦,我们可以采用一种中间件或者抽象层的方法。这种方法允许我们通过一个统一的接口来操作不同的数据库,而不需要修改业务逻辑代码。

示例代码

首先,我们需要定义一个数据库操作的通用接口,然后为每种数据库实现该接口:

// 定义数据库操作接口
class DatabaseInterface {
    async connect() {}
    async query(sql) {}
    async close() {}
}

// 实现MySQL接口
const mysql = require('mysql');
class MysqlDatabase extends DatabaseInterface {
    async connect(config) {
        this.connection = mysql.createConnection(config);
        await new Promise((resolve, reject) => {
            this.connection.connect(err => err ? reject(err) : resolve());
        });
    }

    async query(sql) {
        return new Promise((resolve, reject) => {
            this.connection.query(sql, (err, results) => err ? reject(err) : resolve(results));
        });
    }

    async close() {
        this.connection.end();
    }
}

// 实现MongoDB接口
const { MongoClient } = require('mongodb');
class MongoDatabase extends DatabaseInterface {
    async connect(config) {
        this.client = new MongoClient(config.url, config.options);
        await this.client.connect();
    }

    async query(query) {
        const db = this.client.db(config.database);
        return await db.collection(config.collection).find(query).toArray();
    }

    async close() {
        this.client.close();
    }
}

使用示例

async function main() {
    const mysqlDb = new MysqlDatabase();
    await mysqlDb.connect({ host: 'localhost', user: 'root', password: 'password', database: 'test' });
    const result = await mysqlDb.query("SELECT * FROM users");
    console.log(result);
    await mysqlDb.close();

    const mongoDb = new MongoDatabase();
    await mongoDb.connect({ url: 'mongodb://localhost:27017', database: 'testdb', collection: 'users' });
    const resultMongo = await mongoDb.query({ name: 'John Doe' });
    console.log(resultMongo);
    await mongoDb.close();
}

main().catch(console.error);

通过这种方式,我们可以通过一个统一的 DatabaseInterface 接口来处理 MySQL 和 MongoDB,使得应用逻辑与具体数据库实现解耦。

回到顶部