在 Virtual Populate 中,如何定义 foreignField?

Posted

技术标签:

【中文标题】在 Virtual Populate 中,如何定义 foreignField?【英文标题】:In Virtual Populate, how do you define foreignField? 【发布时间】:2020-07-08 04:35:52 【问题描述】:

考虑下面的代码:

 require("./connection");

// //----------------------------------------------------
const mongoose = require("mongoose");
const Schema = mongoose.Schema;

const PersonSchema = new Schema(
  name: String,
  band: String,
  father: String
);

const ManagerSchema = new Schema(
  name: String,
  country: String
);

const BandSchema = new Schema(
  name: String
);

BandSchema.virtual("members", 
  ref: "Person", // The model to use
  localField: "name", // Find people where `localField`
  foreignField: "band", // is equal to `foreignField`
  // If `justOne` is true, 'members' will be a single doc as opposed to
  // an array. `justOne` is false by default.
  justOne: false,
  options:  sort:  name: -1 , limit: 5  
);

BandSchema.virtual("managers", 
  ref: "Manager", // The model to use
  localField: "name", // Find people where `localField`
  foreignField: "country", // is equal to `foreignField`
  // If `justOne` is true, 'members' will be a single doc as opposed to
  // an array. `justOne` is false by default.
  justOne: false,
  options:  sort:  name: 1 , limit: 5  
);

//BandSchema.set("toObject",  virtuals: true );
BandSchema.set("toJSON",  virtuals: true );

const Person = mongoose.model("Person", PersonSchema);
const Manager = mongoose.model("Manager", ManagerSchema);

const Band = mongoose.model("Band", BandSchema);

/**
 * Suppose you have 2 bands: "Guns N' Roses" and "Motley Crue"
 * And 4 people: "Axl Rose" and "Slash" with "Guns N' Roses", and
 * "Vince Neil" and "Nikki Sixx" with "Motley Crue"
 */
// Person.create([
//   
//     name: "Axl Rose",
//     band: "Guns N' Roses"
//   ,
//   
//     name: "Slash",
//     band: "Guns N' Roses"
//   ,
//   
//     name: "Vince Neil",
//     band: "Motley Crue"
//   ,
//   
//     name: "Nikki Sixx",
//     band: "Motley Crue"
//   
// ]);

// Manager.create([
//   
//     name: "Bibi",
//     country: "South Africa"
//   ,
//   
//     name: "Storm",
//     country: "Italy"
//   ,
//   
//     name: "Wolverine",
//     country: "Canada"
//   ,
//   
//     name: "Jorge Pires",
//     country: "Brazil"
//   
// ]);

// Band.create([ name: "Motley Crue" ,  name: "Guns N' Roses" ]);
/////////////////////////////////////////////////////////////////////////

const app = require("express")();

app.use("/", (req, res) => 
  Band.find()
    .populate("members")
    .populate("managers")
    .exec(function(error, bands) 
      /* `bands.members` is now an array of instances of `Person` */
      console.log(bands);
      res.json(bands);
    );
);

app.listen(3000, () => 
  console.log("We are on port 3000");
);

/**
 *https://***.com/questions/43882577/mongoosejs-virtual-populate
 https://***.com/questions/60875380/populate-virtuals-does-not-seem-to-work-could-anyone-show-me-the-error
 */

考虑相关问题:

Mongoosejs virtual populate

Populate Virtuals does not seem to work. Could anyone show me the error?

我的问题是:你如何定义foreignField

Members 正确填充,但 manager 没有

我知道问题出在foreignField,因为如果我重复来自成员的所有信息,它将正确填充,但现在我们拥有成员并使用相同的数据源进行管理。

【问题讨论】:

【参考方案1】:

经过一些研究,尝试在 Stack Overflow 上回答另一个问题 (mongoose: populate in mongoose which doesn't have any ObjectId ),我意识到它是如何工作的!

考虑部分代码:

BandSchema.virtual("members", 
  ref: "Person", // The model to use
  localField: "name", // Find people where `localField`
  foreignField: "band", // this field here has to match the ref path we want to populate!      
  justOne: false,

);

因此,诀窍是确保 foreignFieldref 模型中的字段匹配,localField 是您可以在填充模型中找到的字段名称:我们必须在 @ 之间进行匹配987654328@ 和localField,更准确地说:localField 的值必须与实际情况下的foreignField 之一匹配,在数据库中,而不是在模式命名过程中。这就是猫鼬可以找到和填充的方式!

现在我意识到我遇到的困难是Virtual 在某种程度上与populate 的操作方向相反。您可以通过像树一样工作来进行图片填充:它只是从id 填充到文档中,而virtual 将填充不包含密钥的文档,包含密钥的文档就是要添加的文档填充过程:它以某种方式落后,这对我来说太难掌握了!要填充的文档没有刚刚填充的字段!令人兴奋!

结论和最后的评论

尽管如此,与populate 相比,我仍然觉得它有限。您仍然必须保留本地关键轨道,这并不能解决例如故事记忆问题,而且根据我的研究它更加有限。我看到的唯一优点是您不需要使用_id,您可以使用任何您喜欢的密钥。我希望在这里使用How to save an JSON file using GridFs 来解决我的问题,但是由于我们仍然必须存储本地密钥,所以我落入了同样的陷阱!

更正

我很高兴我错了! Virtuals 太棒了!并在How to save an JSON file using GridFs 上解决了我的问题,我将在那里更新!

【讨论】:

以上是关于在 Virtual Populate 中,如何定义 foreignField?的主要内容,如果未能解决你的问题,请参考以下文章

如何在带有 FormField 的 Flask / WTForms 中使用 populate_obj?

Mongoose中关联查询populate的使用

如何使 .populate 排除空值?

[Oralce][InMemory]如何确定一个表已经被Populate 到In Memory 中?

如何使用 jest 来监视 Schema.virtual 的猫鼬?

如何正确使用函数 populate()