【问题标题】:Mongoose find by reference fieldMongoose 通过引用字段查找
【发布时间】:2020-03-27 00:57:41
【问题描述】:

我有一个这样的频道架构:

const channelSchema = new mongoose.Schema(
  {
    name: {
      type: String,
      unique: true
    }
  }
);

这是反馈模式:

const feedbackSchema = new mongoose.Schema({
  channelId: {
    type: mongoose.Schema.Types.ObjectId,
    ref: "channel",
    require: true
  }
});

如何按频道名称查找反馈?

Feedback.find({channelId.name : 'something'})

谢谢

【问题讨论】:

    标签: node.js mongoose


    【解决方案1】:

    您无法查询不存在的对象的属性,我建议先查询频道,获取 id 并从那里进行查找。

    const channel = await Channel.findOne({ name });
    const feedback = await Feedback.find({ channelId: channel._id })
    

    【讨论】:

    • 这行得通。由于我是 mongoDB 的新手,我想知道这是否是最佳/推荐的解决方案?
    【解决方案2】:

    由于您没有从通道架构到反馈架构的任何参考,您可以使用猫鼬的populate-virtuals 功能。

    所需的更改如下:

    1-) 像这样替换您的频道架构以使用虚拟填充:

    const mongoose = require("mongoose");
    
    const channelSchema = new mongoose.Schema(
      {
        name: {
          type: String,
          unique: true
        }
      },
      {
        toJSON: { virtuals: true }
      }
    );
    
    // Virtual populate
    channelSchema.virtual("feedbacks", {
      ref: "feedback",
      foreignField: "channelId",
      localField: "_id"
    });
    
    module.exports = mongoose.model("channel", channelSchema);
    

    2-) 使用以下查询查找给定频道名称的反馈:

    请注意,我在查询中对通道名称进行了硬编码,您可以从请求正文或请求查询或请求参数中读取它。

    router.get("/feedback", async (req, res) => {
      const result = await Channel.findOne({ name: "Channel 1" }).populate({
        path: "feedbacks"
      });
    
      res.send(result);
    });
    

    响应会是这样的:

    [
      {
        "_id": "5de5509476a9c34048c1d23d",
        "name": "Channel 1",
        "__v": 0,
        "feedbacks": [
          {
            "_id": "5de5512d7d87de2d4c6b38d2",
            "channelId": "5de5509476a9c34048c1d23d",
            "__v": 0
          },
          {
            "_id": "5de551357d87de2d4c6b38d3",
            "channelId": "5de5509476a9c34048c1d23d",
            "__v": 0
          }
        ],
        "id": "5de5509476a9c34048c1d23d"
      }
    ]
    

    或者如果您只对反馈感兴趣,您可以通过result.feedbacks 访问它们:

    router.get("/feedback", async (req, res) => {
      const result = await Channel.findOne({ name: "Channel 1" }).populate({
        path: "feedbacks"
      });
    
      res.send(result.feedbacks);
    });
    

    这会给你一系列这样的反馈:

    [
        {
            "_id": "5de5512d7d87de2d4c6b38d2",
            "channelId": "5de5509476a9c34048c1d23d",
            "__v": 0
        },
        {
            "_id": "5de551357d87de2d4c6b38d3",
            "channelId": "5de5509476a9c34048c1d23d",
            "__v": 0
        }
    ]
    

    【讨论】:

      【解决方案3】:

      您可以使用插件mongoose-find-by-reference

      Step.1 安装

      npm i -S mongoose-find-by-reference
      

      npm link Github link

      Step.2 plugin()插件

      const mongoose = require("mongoose");
      
      // Require mongoose-find-by-reference
      const { MongooseFindByReference } = require('mongoose-find-by-reference');
      
      await mongoose.connect("mongodb://localhost:27017/test")
      
      const channelSchema = new mongoose.Schema(
        {
          name: {
            type: String,
            unique: true
          }
        }
      );
      
      
      const feedbackSchema = new mongoose.Schema({
        channelId: {
          type: mongoose.Schema.Types.ObjectId,
          ref: "channel",
          require: true
        }
      });
      
      // Execute function plugin() on schema with Reference paths
      feedbackSchema.plugin(MongooseFindByReference);
      
      
      const Channel= mongoose.model('channel', channelSchema );
      const Feedback= mongoose.model('feedback', feedbackSchema );
      

      Step.3 随便用!

      const { _id } = await Channel.create({ name: "C" })
      
      await Feedback.create({channelId : _id})
      
      /** Its conditions will be auto automatically replaced with :
      {
        channelId: {
          $in: [
            /* ObjectIDs for Eligible channels */
          ],
        },
      }
       */
      const findResult = await Feedback.find({channelId.name : 'C'})
      
      

      【讨论】:

        猜你喜欢
        • 2021-05-29
        • 2020-11-27
        • 2016-09-17
        • 2015-09-19
        • 2013-01-09
        • 1970-01-01
        • 2022-11-11
        • 2018-02-03
        • 2013-10-23
        相关资源
        最近更新 更多