如何在 ejs 中访问 populated() 数据库查询结果的属性?

How can I access the properties of a populated() database query result in ejs?

我试图在前端访问和显示填充的数据库查询的结果,但是当我尝试访问填充的变量的属性时,我得到了未定义的结果。下面是我的 mongoose find 方法引用的模式。

报价架构

const express = require('express')
const mongoose = require('mongoose')
const Schema = mongoose.Schema
const User = require('../models/users')

let QuoteSchema = new Schema({
    author: {
        type: String,
        trim: true
    },
    quote: {
        type: String,
        unique: [true, "this quote already exists."],
        trim: true
    },
    submittedBy: [{
        type: Schema.Types.ObjectId,
        ref: 'users'
        // trim: true,
        // required: true
    }]
}, {
    timestamps: true
})

const Quote = mongoose.model('quotes', QuoteSchema)
module.exports = Quote

用户架构

const express = require('express')
const mongoose = require('mongoose')
const Schema = mongoose.Schema

let UserSchema = new Schema ({
    username: {
        type: String,
        unique: [true, "This username is taken."],
        trim: true,
    },
    email: {
        type: String,
        unique: [true, "This email is already being used."],
        trim: true
    },
    password: {
        type: String,
        trim: true
    },
    favorites: []
}, {
    timestamps: true,
})

const User = mongoose.model('users', UserSchema)
module.exports = User

这是猫鼬查询。 populate 方法附加到 find 方法,sort 方法附​​加到 populate 方法。结果的typeof确认它是一个对象,但我认为当它到达ejs时它不会保持这种状态。

数据库查询和post路由文件中的请求

router.get('/', (req, res, next) => {
    console.log("beginning query...")
    const flashMessages = res.locals.getMessages()
    if (req.user) {
        Quote.find({}).populate('submittedBy').sort({ _id: -1 })
        .exec((err, results) => {
            console.log(typeof results) // returns "object"
            err ? console.log(err) : res.render('index', { quotes: results, user: req.user, csrfToken: req.csrfToken() });
        })
    }
})


router.post('/quotes', (req, res, next) => {
    if(req.isAuthenticated()) {
        let quote = new Quote({
            author: req.body.author,
            quote: req.body.quote,
            submittedBy: req.body.userId
        })

        quote.save((err, quote) => {
            if (err) {
                console.log(err)
            } else {
                console.log("Added the quote \"" + quote.quote + "\" by " + quote.author + ".")
                res.redirect('/')
            }
        })
        .catch(next)
    } else {
        req.flash("restricted", "You must first login before you can add quotes to the community feed.")
        res.redirect('/')
    }
})

我认为这是发生错误的地方。在最后一个 span 标签上,引用 [i].submittedBy returns 整个 "submittedBy" 变量,这意味着 population 方法做了它应该做的。但是,如果我尝试访问该对象上的 属性,它 returns 未定义。引号[i].submittedBy.username returns 未定义。当我检查元素时,submitted 被引号包围,所以我认为出于某种原因现在它是一个字符串。但是如果我尝试使用 JSON.parse() 或 JSON.stringify(),我在这两种情况下都会出错。我不知道该怎么办。请帮忙!

Ejs 渲染

<% for(var i = 0; i < quotes.length; i++) {%>
    <li class="quote">
        <i class="fa fa-close fa-quote-close move hidden"></i>
        <i class="fa fa-heart hidden"></i>
        <span class="make-bold nhauthorValues" id="<%= quotes[i]._id %>" contenteditable="true"><%= quotes[i].author %></span> once said: "<span class="quoteValues" id="<%= quotes[i]._id %>" contenteditable="true"><%= quotes[i].quote %></span>"
        <span class="by"><%= quotes[i].submittedBy.username %></span>
    </li>
<% } %>

您插入实例的方式可能有误:

let quote = new Quote({
   author: req.body.author,
   quote: req.body.quote,
   {$push:{submittedBy: req.body.userId}}
});

尝试使用这个也许会奏效, 如果它不提供您在渲染之前填充结果后获得的对象的快照。

你会得到一个 submittedBy 数组,所以你不能直接访问用户名,因为在模式中你已经给定了数组类型。

使用大括号代替方括号。

你可以这样做:

const express = require('express')
const mongoose = require('mongoose') 
const Schema = mongoose.Schema
const User = require('../models/users')

let QuoteSchema = new Schema({
 author: {
     type: String,
     trim: true
 },
 quote: {
     type: String,
     unique: [true, "this quote already exists."],
     trim: true
 },
 submittedBy: {
     type: Schema.Types.ObjectId,
     ref: 'users'
     // trim: true,
     // required: true
 } //removed square brackets
 }, {
timestamps: true
})

const Quote = mongoose.model('quotes', QuoteSchema)
module.exports = Quote

现在,如果您只有一个用户提交报价,请按照与之前相同的步骤进行操作,忽略答案中的第一个步骤。如果多个用户可以然后 submittBy 将是一个数组并相应地访问它。