【问题标题】:sailsjs use mongodb without ORMSailsjs 使用没有 ORM 的 mongodb
【发布时间】:2017-09-29 00:45:35
【问题描述】:

我想将 mongodb 与sails 一起使用,但没有任何ORM。所以下面是我连接 mongodb 的服务。
服务:

//DbService.js

    const MongoClient = require('mongodb').MongoClient;

    module.exports = {
      db:function(req, res){
        var connect=MongoClient.connect("mongodb:***********").then(function (err, database) {
          if(err) console.log(err);
          else{
            database=database.db('*****');
            return connect;
          }  

        });  
      }
    }

连接后,我在控制器中调用了它,但出现 TypeError: Cannot read property 'then' of undefined。

控制器:

//HomeControlelr.js
    module.exports = {
            index:function(req, res){
                DbService.db().then(function(err,db) {
                    console.log(db);
                })
            }
    };

【问题讨论】:

  • 为什么要这样做?水线是大多数人首先使用 Sails 的重要原因。
  • 我只需要获取数据。我不想为所有集合编写 scema。
  • MongoClient.connect() 似乎没有返回Promisenpmjs.com/package/mongodb#connecting-to-mongodb
  • 作为替代方案,您可以随时使用水线native features

标签: node.js mongodb promise sails.js q


【解决方案1】:

首先是npm i mongodb,因为您需要用new ObjectID(idStr) 包装任何ID。

那么你可以这样做:

const collection = Pet.getDatastore().manager.collection(Pet.tableName);
const res = await collection.find({ name: { $regex: /blue/ } });
const dataWithObjectIds = await res.toArray();
const dataWithIds = JSON.parse(JSON.stringify(rawDataArr).replace(/"_id"/g, '"id"'));

我创建了一个辅助函数来为我们完成所有这些工作:

/**
 * Use by chaining as if you were acting on a collection. So can use .find .aggregate etc.
 * Returns json searializable data.
 *
 * @param {class} model A model
 * @param {number} cnt - Number of chains on this, so I know when it reached the end
 */
function nativeMongoQuery(model, cnt) {

  const collection = model.getDatastore().manager.collection(model.tableName);

  let callCnt = 0;

  let req;

  const proxy = new Proxy({}, {
    get: (_, method) => (...args) => {

      if (!req) req = collection[method](...args);
      else req = req[method](...args);

      callCnt++;

      if (callCnt === cnt) {
        return (async function() {
          const rawDataArr = await req.toArray();
          return JSON.parse(JSON.stringify(rawDataArr).replace(/"_id"/g, '"id"'));
        })();
      } else {
        return proxy;
      }
    }
  });

  return proxy;

}

module.exports = nativeMongoQuery;

我不喜欢 JSON 解析、字符串化和全局替换。但是如果我不进行字符串化,那么 mongo _id 都是ObjectIds。

像这样使用它:

const { ObjectId } = require('mongodb');

function makeObjectId(id) {
   return new ObjectId(id);
}

const ownerIds = ['5349b4ddd2781d08c09890f4', '5349b4ddd2781d08c09890f5']
const ownerObjectIds = ownerIds.map(makeObjectId);
await nativeMongoQuery(Pet, 2).find({ owner: { $in: ownerObjectIds } }).sort({ dueAt: 1 });

这是另一个例子:

const mostRecentlyCreatedPets = await nativeMongoQuery(Pet, 1).aggregate([
  { $match: { owner: { $in: ownerObjectIds } } },
  { $sort: { createdAt: -1 } },
  { $limit: 1 }
]);

cnt 参数告诉你有多少东西被锁在那里。

【讨论】:

    【解决方案2】:

    正如您在docs 中看到的,MongoClient.connect() 不返回 Promise 对象。而不是这个使用回调函数

    module.exports = {
      db:function(){
        var connect = MongoClient.connect("mongodb:***********", function (err, database) {
          //...
          }  
        });  
      }
    }
    

    顺便说一句。您在控制器中调用 DbService.db 函数也会失败,因为您的服务函数也不会返回 Promise

    在继续之前,请阅读一些有关 Promises 和回调函数的内容

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-03
      • 1970-01-01
      • 1970-01-01
      • 2013-12-13
      • 2020-09-06
      相关资源
      最近更新 更多