mongoose自带填充自定义查询

时间:2018-02-23 08:17:07

标签: node.js mongoose mongoose-schema mongoose-populate

我试图在mongoose中创建自定义查询方法 - 类似于popong() - mongoose的功能。我有以下两种简单的模式:

const mongoose = require(' mongoose')

const bookSchema = new mongoose.Schema({
    title: String,
    author: {type: mongoose.Schema.Types.ObjectId, required: true, ref: 'Author'}
}, {versionKey: false})

const authorSchema = new mongoose.Schema({
    name: String
}, {versionKey: false})

现在,我想要检索作者信息以及作者撰写的书籍。据我所知,mongoose提供自定义查询,因此我的想法是编写一个自定义查询函数,如:

authorSchema.query.populateBooks = function () {
    // semi-code:
    return forAll(foundAuthors).findAll(books)
}

现在,为了获得所有作者和所有书籍,我可以简单地运行:

authorModel.find({})。populateBooks(的console.log)

这应该是这样的:

[ {name: "Author 1", books: ["Book 1", "Book 2"]}, {name: "Author 2", books: ["Book 3"] } ]

不幸的是,它不起作用,因为我不知道如何访问我之前在populateBooks函数中选择的作者列表。我在自定义查询功能中需要的是先前选择的文档的集合。 例如,authorModel.find({})已经返回作者列表。在populateBooks()中,我需要遍历此列表以查找所有作者的所有书籍。任何人都知道我如何访问这个集合或者它是否可能?

1 个答案:

答案 0 :(得分:0)

populate:"人口是使用来自其他集合的文档自动替换文档中指定路径的过程" (来自我链接的文档)。

根据您的问题,您不会寻找人口。你的是一个简单的查询(下面的代码是为了实现你最后给出的结果。注意你的books字段有一个字符串数组的值,我假设这些是标题)。此外,请注意以下代码将与您已经提供的模型一起使用,但这是一个我推荐的错误实现 - 出于多种原因:效率,优雅,潜在错误(例如,具有相同名称的作者) ),见代码后的注释:

Author.find({}, function(err, foundAuthors){
    if (err){
        console.log(err); //handle error
    }
    //now all authors are objects in foundAuthors
    //but if you had certain search parameters, foundAuthors only includes those authors
    var completeList = [];
    for (i=0;i<foundAuthors.length;i++){
        completeList.push({name: foundAuthors[i].name, books: []});
    }
    Book.find({}).populate("author").exec(function(err, foundBooks){
        if (err){
            console.log(err); //handle err
        }
        for (j=0;j<foundBooks.length;j++){
            for (k=0;k<completeList.length;k++){
                if (completeList[k].name === foundBooks[j].author.name){
                    completeList[k].books.push(foundBooks[j].title);
                }
            }
        }
        //at this point, completeList has exactly the result you asked for
    });
});

但是,正如我所说,我建议不要使用此实现,这是基于您已经提供的代码而不更改它。

我建议您更改作者架构以包含books属性:

var AuthorSchema = new mongoose.Schema({
    books: [{
        type: mongoose.Schema.Types.ObjectId,
        ref: "Book"
    }]
    //all your other code for the schema
});

并将所有书籍添加到各自的作者。这样,你需要做的就是获得一个对象数组,每个对象都包含一个作者和他的所有书籍是一个查询:

Author.find({}).populate("books").exec(function(err, foundAuthors){
    //if there's no err, then foundAuthors is an array of authors with their books
});

这比我之前提供的解决方案更简单,更高效,更优雅,更有效,基于您现有的代码而不改变它。