如何使用Node.JS和Mongoose将数据从MongoDB获取到简单数组?

问题描述:

假设这是我的MongoDB模式:

Let's say this is my MongoDB schema:

    var shopSchema = new mongoose.Schema({
        nameShop: String,
        products: [
            {
                type: mongoose.Schema.Types.ObjectId,
                ref: 'Product'
            }]
    });

    var productSchema = new mongoose.Schema({
        nameProduct: String,
        fruits: [
            {
                type: mongoose.Schema.Types.ObjectId,
                ref: 'Fruit'
            }
        ]
    });

    var fruitSchema = new mongoose.Schema({
        nameFruit: String,
        price: Number
    });

module.exports = {
    Shop: mongoose.model('Shop', shopSchema),
    Product: mongoose.model('Product', productSchema),
    Fruit: mongoose.model('Fruit', fruitSchema)
}

我知道我可以通过这种方式获取数据,但是代码的结果是一个难看的数组

I know that I can get data in this way, but result of that code is an "ugly" array

var Schema = require('../model/schema');
    Schema.Shop.find({}).populate({
        path: 'products',
        model: 'Product',
        populate: {
            path: 'fruits',
            model: 'Fruit'
        }
    }).exec(callback);

是否可以通过这种方式从数据中获取数据,从而获得良好的数组?例如:

Is it possible to get data from this schema in way that I will have nice array? E.g.:

var MyArray = [
                  { nameShop: "Tesco", nameProduct: "New", nameFruit: "Apple", price: 10 },
                  { nameShop: "Tesco", nameProduct: "New", nameFruit: "Pinapple", price: 4 },
                  { nameShop: "Eko", nameProduct: "Old", nameFruit: "Kiwi", price: 8 },
                  { nameShop: "Makro", nameProduct: "Fresh", nameFruit: "Pear", price: 7 },
                  { nameShop: "Carefour", nameProduct: "New", nameFruit: "Orange", price: 6 }
              ];

您可以使用聚合框架路由,该路由具有通过 $ unwind 运算符。这将为应用展开的列表数据字段的每个元素生成一条新记录。它基本上使数据变平。

You could go the aggregation framework route, which has the capacity to flatten the arrays through the $unwind operator. This will generate a new record for each and every element of the list data field on which unwind is applied. It basically flattens the data.

展平数据后,您需要 $ lookup 运算符对产品$进行加入 c $ c>字段添加到产品集合中。重复此过程以嵌套水果模式。

After flattening the data you would require the $lookup operator to do a "join" on the products field to the products collection. Repeat the process for the nested fruits schema.

让我们看一个示例(未经测试)以更好地理解这一点

Lets see an example (untested) to understand this better

var Schema = require('../model/schema');
Schema.Shop.aggregate([
    { "$unwind": "$products" },
    {
        "$lookup": {
            "from": "products",
            "localField": "products",
            "foreignField": "_id",
            "as": "product"
        }
    },
    { "$unwind": "$product" },
    { "$unwind": "$product.fruits" },
    {
        "$lookup": {
            "from": "fruits",
            "localField": "product.fruits",
            "foreignField": "_id",
            "as": "fruits"
        }
    },  
    {
        "$project": {
            "nameShop": 1,
            "nameProduct": "$product.nameProduct",
            "nameFruit": "$fruits.nameFruit",
            "price": "$fruits.price",
        }
    }
]).exec(function (err, result){
    if (err) throw err;
    console.log(result);
})

免责声明:上面是未经测试的代码,仅通过做几个假设就可以证明您正在使用支持 $ lookup 运算符,您可以执行在mongo shell中使用相同的聚合查询。

DISCLAIMER: The above is untested code which only serves as a guide by making a couple of assumptions that you are running the code in a test environment with the latest MongoDB and mongoose versions that support the $lookup operator AND that you can perform the same aggregation query in mongo shell.