简体   繁体   English

Node.JS、Express 和 MongoDB :: 多个集合

[英]Node.JS, Express & MongoDB :: Multiple Collections

I'm using Node.JS, Express, MongoDB and EJS.我正在使用 Node.JS、Express、MongoDB 和 EJS。 I have a question regarding multiple MongoDB collections under one database, and calling them to use on the front-end.我有一个关于一个数据库下的多个 MongoDB 集合的问题,并调用它们在前端使用。 I have 3 collections, and after much research haven't found how to call more than one collection without errors.我有 3 个集合,经过大量研究还没有找到如何正确调用多个集合。

I understand that it wouldn't be a problem to store everything under one collection, but I feel like the best approach would be to separate them out by category.我知道将所有内容存储在一个集合中不会有问题,但我觉得最好的方法是按类别将它们分开。 Here's my db/collection call:这是我的 db/collection 电话:

app.use(express.bodyParser());
var MongoClient = require('mongodb').MongoClient;

app.get('/', function(req, res){
  MongoClient.connect("mongodb://localhost:27017/michael", function(err, db) {
    if(!err) {
      console.log("We are connected");
    }
    db.collection("portfolio", function(err, collection) {
      collection.find().sort({order_num: 1}).toArray(function(err, result) {
        var portfolio = [];
        if (err) {
          throw err;
        } else {
          for (i=0; i<result.length; i++) {
            portfolio[i] = result[i];
          }
          res.render('index.html', {portfolio: portfolio});
        }
      });
    });
  });
});

How could I make multiple calls to additional collections, such as an "about" collection, etc?如何多次调用其他集合,例如“关于”集合等? I tried adding another...我尝试添加另一个...

db.collection("about", function(err, collection) {

...within... ...之内...

MongoClient.connect("mongodb://localhost:27017/michael", function(err, db) {

...but it gives me errors in the Terminal console log. ...但它在终端控制台日志中给了我错误。

Thanks in advance.提前致谢。

EDIT:编辑:

Here's what I'm trying to do, which gives me an error:这是我想要做的,这给了我一个错误:

app.get('/', function(req, res){
  MongoClient.connect("mongodb://localhost:27017/michael", function(err, db) {
    if(!err) {
      console.log("We are connected");
    }
    db.collection("portfolio", function(err, collection) {
      collection.find().sort({order_num: 1}).toArray(function(err, result) {
        var portfolio = [];
        if (err) {
          throw err;
        } else {
          for (i=0; i<result.length; i++) {
            portfolio[i] = result[i];
          }
          res.render('index.html', {portfolio: portfolio});
        }
      });
    });
     // Here's the additional collection call:
     db.collection("about", function(err, collection) {
      collection.find().sort({order_num: 1}).toArray(function(err, result) {
        var about = [];
        if (err) {
          throw err;
        } else {
          for (i=0; i<result.length; i++) {
            about[i] = result[i];
          }
          res.render('index.html', {about: about});
        }
      });
    });
  });
});

Here's the error from the console:这是来自控制台的错误:

ReferenceError: /Volumes/Files/WebDev/RHC/michael/michael/views/index.html:62
60|               <div class="row-fluid">
61|                 <ul id="work" class="thumbnails">
>> 62|                     <% for(i=0; i<portfolio.length; i++) { %>
63|                         <% if (portfolio[i].proj_type == "work") { %>
64|                             <% var newLine = ""; %>
65|                             <% var fancyBox = ""; %>

portfolio is not defined

So I have two collections in MongoDB under the db called "michael", and I'm trying to call both of them under one MongoClient.connect().因此,我在 MongoDB 中名为“michael”的数据库下有两个集合,我试图在一个 MongoClient.connect() 下调用它们。 I'm then sending the results to the front-end (via EJS) in two arrays: "portfolio" and "about".然后我将结果以两个数组发送到前端(通过 EJS):“portfolio”和“about”。 It seems that when I do this, it renders "portfolio" undefined.似乎当我这样做时,它使“投资组合”未定义。 Hope that makes sense.希望这是有道理的。

Ok, using aesede's solution plus my own tinkering, I got it to render two collections.好的,使用 aesede 的解决方案加上我自己的修补,我得到了它来渲染两个集合。 It could probably use some finessing but here's what I got:它可能会使用一些技巧,但这是我得到的:

// GLOBAL ARRAYS FOR STORING COLLECTION DATA
var collectionOne = [];
var collectionTwo = [];
app.get('/', function(req, res){
  MongoClient.connect("mongodb://localhost:27017/michael", function(err, db) {
    if(!err) {
      console.log("We are connected");
    }
    db.collection("collectionOne", function(err, collection) {
      collection.find().sort({order_num: 1}).toArray(function(err, result) {
        if (err) {
          throw err;
        } else {
          for (i=0; i<result.length; i++) {
            collectionOne[i] = result[i];
          }
        }
      });
      db.collection("collectionTwo", function(err, collection) {
        collection.find().sort({order_num: 1}).toArray(function(err, result) {
          if (err) {
            throw err;
          } else {
            for (i=0; i<result.length; i++) {
              collectionTwo[i] = result[i];
            }
          }
        });
      });
      // Thank you aesede!
      res.render('index.html', {
        collectionOne: collectionOne,
        collectionTwo: collectionTwo
      });
    });
  });
});

The only bug, per se, that I found, was that when Node restarted and I hit "refresh" in the browser, I didn't see any content being rendered in the HTML.我发现的唯一错误是,当 Node 重新启动并在浏览器中点击“刷新”时,我没有看到任何内容在 HTML 中呈现。 However, any subsequent refresh showed the content consistently.但是,任何后续刷新都会始终如一地显示内容。

There is actually a really simple, intuitive answer to this problem.对于这个问题,实际上有一个非常简单、直观的答案。 It's definitely not elegant and I do think an update to Express, Mongoose and NodeJS should include a preset way of doing this rather than having to logically think the process through.这绝对不优雅,我确实认为对 Express、Mongoose 和 NodeJS 的更新应该包含一种预设的方式来做到这一点,而不必从逻辑上思考这个过程。

All you have to do is nest your find() calls into each other for each collection you want to pass through to the page.您所要做的就是为要传递到页面的每个集合将您的 find() 调用相互嵌套。 Example below:下面的例子:

app.get("/", function(req, res) {
     Collection.find({}, function(err, collection) {
          if(err) {
               console.log(err);
          } else {
               Collection2.find({}, function(err, collection2) {
                    if(err) {
                         console.log(err)
                    } else {
                         res.render("page", {collection: collection, collection2: collection2});
                    }  
               }); 
          }
     });
});

You can keep doing this infinitely but obviously this concept does not scale.你可以无限地这样做,但显然这个概念不能扩展。 If you had thirty different collections to pass through, this would be a really inconvenient way to do so.如果您有 30 个不同的集合要通过,这将是一种非常不方便的方式。

From the research I've done, this is not as simple as it should be because the Collection.find() method is actually a Promise function.从我所做的研究来看,这并不像它应该的那么简单,因为 Collection.find() 方法实际上是一个 Promise 函数。 If it wasn't a promise function, we could simply just run the find() method for each collection, pass the results into a global object, and pass the entire object through the render.如果它不是一个 promise 函数,我们可以简单地为每个集合运行 find() 方法,将结果传递给一个全局对象,然后通过渲染传递整个对象。 You can't do this though because the global variable will be initialized and passed through the render before the promise function finishes.但是你不能这样做,因为全局变量将在 promise 函数完成之前被初始化并通过渲染。 You end up passing an empty object through the render.您最终通过渲染传递了一个空对象。 I know this because I tried it.我知道这是因为我试过了。

I have no experience with Promise functions.我对 Promise 函数没有经验。 I'm going to do some research on them and see if there is a way to structure your code to take advantage of the promise function and execute this task more "elegantly".我将对它们进行一些研究,看看是否有一种方法可以构建您的代码以利用 promise 函数并更“优雅地”执行此任务。 But in the mean time, use my example above, as I believe it is the most intuitive way to accomplish this.但同时,请使用我上面的示例,因为我认为这是实现此目的的最直观的方法。

I'm with same problem, and now I know it has to do with the fact that you cannot res.render() twice.我有同样的问题,现在我知道这与你不能 res.render() 两次的事实有关。 There's a solution some recommend: using socket.io .有人推荐了一个解决方案:使用socket.io I'd like to know if there's another solution, in my case I want to get recipes and authors from 2 different mongoDB collections but I can't do it with only 1 res.render(), can't believe node.js + express + mongoose won't accomplish something that simple to do in let's say... LAMP.我想知道是否有另一种解决方案,在我的情况下,我想从 2 个不同的 mongoDB 集合中获取食谱和作者,但我无法仅使用 1 个 res.render() 来完成,无法相信 node.js + express + mongoose 不会完成这么简单的事情,比如说...... LAMP。

app.get("/customer",function(req,res) {
    var orders={}; //Create Empty order Object
    var products={}; //Create Empty product Object
    Product.find({},function (err,allproducts) {
        if (err) {
            console.log(err);
        } else {
            //Find Collection And Assign It To Object
            products=allproducts;             
        }
    });
    Order.find({}).sort({"date":'desc'}).exec(function(err, allOrders) {
        if (err) {
            console.log(err);
        } else {
            //find order collection and sort it in desending order and assign it to order object  
            orders=allOrders;
            res.render("./customer/dashboard",{products:products , orders:orders});
        }
    });

});

I faced the same issue i solved it with above mechanism i recommend using empty objects instead of arrays as MongoDb returns object and also you may face some type errors when you use arrays instead of objects我遇到了同样的问题,我用上述机制解决了它我建议使用空对象而不是数组作为 MongoDb 返回对象,而且当您使用数组而不是对象时,您可能会遇到一些类型错误

function mongoConnection() {
    return new Promise((res, rej) => {
        try {
            MongoClient.connect(conn_url, {},
                function (err, client) {
                    if (err) { res(false); }
                    else {
                        promise_db_connection = new Promise((resolve, reject) => {
                            var db = client.db(Database);
                            resolve(
                                {
                                    'collection_1': db.collection("collection_1"),
                                    'collection_2': db.collection("collection_2"),
                                    'collection_3': db.collection("collection_3")
                                }
                            );
                            res(true);
                        });
                    }
                }
            );
        } catch (error) {
            res(false);
        }
    })
}

mongoConnection().then((result) => {
    console.log(result ? 'Connection Successful' : 'Connection Failed');
})

app.get('/customer', (req, res) => {
    var product = [], order = []
    promise_db_connection.then((result) => {
        result.collection_1.find({}).toArray((err, data) => {
            if (!err) product = data;
            result.collection_2.find({}).toArray((err, data) => {
                if (!err) order = data;
            })
            res.render("page", { product: product, order: order });
        })

    })
})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM