【问题标题】:Mongoose | NodeJS : How to assing two 'ref' to same model term and populate it?猫鼬 | NodeJS:如何将两个'ref'分配给同一个模型术语并填充它?
【发布时间】:2020-01-14 22:12:36
【问题描述】:

更新: 我试过这个:

  ad:[{ type: mongoose.Types.ObjectId, ref: 'Ad' }],
  car:[{ type: mongoose.Types.ObjectId, ref: 'Car' }]

它有效,但我无法订购,所以仍然卡住..

.populate('ad')
.populate('car')
.sort({createdAt:-1}) 

(我想按 createdAt 或 updatedAt 时间订购)

这就是我在以下之前尝试过的:

我真的被困住了,我也知道我只需要一点帮助就可以解决它。

我正在处理 nodeJS 和 HBS 项目(网站为 craigslist)。

我有不同的模型,用于不同的类别: 乔布斯有自己的看法 汽车有自己的看法 等等……

我有一个用户模型,其中包含他们发布的每个广告。

const userSchema = new Schema({
  email:{
    type:String,
    required:true,
    trim:true,
    lowercase:true,
    match: [/\S+@\S+\.\S+/, 'is invalid']
  },
  password:{
    type:String,
    required:true,
    trim:true
  },
  ad:[{ type: mongoose.Types.ObjectId, ref: 'Ad'},{ type: mongoose.Types.ObjectId, ref:'Car'}]
}, {
  timestamps: {
    createdAt: "created_at",
    updatedAt: "updated_at"
  }
});

如你所见,我有这个:

ad:[{ type: mongoose.Types.ObjectId, ref: 'Ad'},{ type: mongoose.Types.ObjectId, ref:'Car'}]

在我的 mongoose 数据库中,我可以通过 $push 保存这些数据:

.then(ad => {
            User.updateOne({email:ad.email},{$push:{ad:ad._id}})
            .then(() => res.render('ads/test'))
          })

一切正常,mongodb:

//mongodb database
> db.users.find().pretty()
{
    "_id" : ObjectId("5e1e28663128e9643c523712"),
    "ad" : [
        ObjectId("5e1e28633128e9643c523711"),
        ObjectId("5e1e28733128e9643c523713")
    ],
    "email" : "whatever@whatever.com",
    "password" : "$whatever$whatever.whatever",
    "created_at" : ISODate("2020-01-14T20:45:26.262Z"),
    "updated_at" : ISODate("2020-01-14T20:45:39.694Z"),
    "__v" : 0
}

所以,我有两个来自不同模型的广告(模型 A:职位类别发布,模型 B:汽车类别发布)及其 ID:

"ad" : [
            ObjectId("5e1e28633128e9643c523711"),
            ObjectId("5e1e28733128e9643c523713")
        ]

之后,在我的用户控制器中,我尝试填充...但我只是在一个模型中完成:

module.exports.myAds = (req, res, next) => {
  User.findOne({email:req.session.currentUser.email})
    .populate({path: 'ad', options: { sort: { 'updated_at': -1 }}})
    .then(ads => {
      console.log(ads)
      res.render('users/my-ads', { ads:ads } )
    })
    .catch(err => next(err))
}

拜托,我需要解决这个问题。我做错了什么?

我寻找相同的解释,但没有一个适合我。

我也试过,将ad拆分成:

 ad:[{test_1:{ type: mongoose.Types.ObjectId, ref:'Ad'}},{test_2:{type: mongoose.Types.ObjectId, ref:'Car'}}]

但甚至不是一个好的结果。 也许我在 $push 到 test_1 / test_2 甚至当我填充时错了?

【问题讨论】:

  • 您是否尝试过将 2 个 id 放在一个数组中,以便将其存储为具有 2 个 id 的数组数组ad:[[test_1:{ type: mongoose.Types.ObjectId, ref:'Ad'},test_2:{type: mongoose.Types.ObjectId, ref:'Car'}]]
  • 我如何 $push 这个来自:.then(ad => { User.updateOne({email:ad.email},{$push:{ad:ad._id}}) .then (() => res.render('ads/test')) }) 我的意思是,如何在每个数组中正确插入¿?
  • 你可以{$push:{ad.$.test1: {ad.id}, ad.$.test2:{car.id}}我想
  • 但嵌套数组必须是我现在看到的不同模式
  • 我就是这么做的。现在,我在 populate() 之后处理,并创建一个包含广告和汽车数据的新数组,之后我将按 updateAt 元素排序。

标签: node.js mongoose populate


【解决方案1】:

在这种情况下,填充对用户来说并不理想。 您应该尝试将聚合与 $lookup 运算符一起使用 见:https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/ 通过这种方式,您可以更好地控制数据

【讨论】:

  • 我不明白如何将不同模型加入或聚合到同一个模型。可以举个例子吗?
  • 聚合是一个管道,这意味着对于每个连续的运算符,输入来自前一个运算符结果的输出。因此,在管道中,您可以进行任意数量的串行查找。先研究一下聚合,其实很简单docs.mongodb.com/manual/reference/method/…
【解决方案2】:

最后,我解决了这个问题:

//ads.controller 
   // here I $push both kinds of ads (both models, ad and car) to user model


    User.findOne({email:email})
          .then(user => {
            if(user !== null){
              console.log(`User ${user.email} already exists`)
              newCarAd.save()
              .then(ad => {
                User.updateOne({email:ad.email},{$push:{car:ad._id}})
                .then(() => res.render('ads/test'))
              })
              .catch(error => {
                if (error instanceof mongoose.Error.ValidationError) {
                  renderWithErrors(error.errors)
                } else {
                  next(error)
                }
              })

// user model

    const userSchema = new Schema({
    ...

      ad:[{ type: mongoose.Types.ObjectId, ref: 'Ad' }],
      car:[{ type: mongoose.Types.ObjectId, ref: 'Car' }]
    }, {
      timestamps: {
        createdAt: "created_at",
        updatedAt: "updated_at"
      }
    });

//user controller 
//to populate and handle object from both models -pushed from 
//ads.controller-
    module.exports.myAds = (req, res, next) => {
      User.findOne({email:req.session.currentUser.email})
        .populate('ad')
        .populate('car')
        .sort({createdAt:-1})
        .then(ads => {
          //join all ads in same object to my-ads views
          const arrayUserAds = [...ads.ad,...ads.car];
  const allUserAds = arrayUserAds.sort((a,b) => {return b.updated_at -a.updated_at})

          res.render('users/my-ads', { ads:allUserAds } )
        })
        .catch(err => next(err))
    }

【讨论】:

    猜你喜欢
    • 2020-11-02
    • 1970-01-01
    • 2018-12-15
    • 2016-05-16
    • 2021-09-19
    • 2021-06-29
    • 2021-04-24
    • 2021-05-16
    • 1970-01-01
    相关资源
    最近更新 更多