我试图在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()中,我需要遍历此列表以查找所有作者的所有书籍。任何人都知道我如何访问这个集合或者它是否可能?
答案 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
});
这比我之前提供的解决方案更简单,更高效,更优雅,更有效,基于您现有的代码而不改变它。