MongoDb:将模型字段从字符串数组修改为引用另一个模型的 ID 数组的最佳方法是什么?
MongoDb: What's the best approach to modify a model field from an array of strings to an array of ids that would refer to another model?
我有一个 Profile
模型,其中包含此字段:
interests: {
type: [String],
},
我的应用 运行 已经有一段时间了。所以这意味着对于几个文档,这个字段已经填充了一个字符串数组。
为了实现某些目标,我需要创建一个带有字段 name
的模型 Interest
,然后在 Profile
中引用它,如下所示:
interests: [{
type: Schema.Types.ObjectId,
ref: "interests",
}],
字段 name
应包含 Profile.interests
中已经存在的 string
个兴趣。
这是我认为我会遵循的方法:
- 创建
Interest
模型。
- 用现有的
Profile.interests
个字符串填充 name
字段。
一种。执行此操作时,将 Profile.interests
替换为新创建的 Interest
文档的 _ids
。
b.确保 Interest.name
是唯一的。
C。删除空格。
- 应用中后台使用
interests
的地方,用populate
填充。
感觉这不是一个安全的操作。所以我想听听您对此的看法。有更好的方法吗?我应该避免这样做吗?
谢谢。
第 1 步:
- 为兴趣创建模型,
- 根据兴趣架构指定所需字段并为特定字段设置属性
- 根据您的要求在选项中指定集合名称
- 创建模型并在模型中指定您想要的名称
const InterestsSchema = new mongoose.Schema(
{ name: { type: String } },
{ collection: "interests" }
);
const Interests = mongoose.model("Interests", InterestsSchema);
- 而不是删除
interests
字段添加新字段 interest
(您可以选择所需的字段),为了安全起见,只要您觉得当前更新有效正确地你可以删除它,更新配置文件架构,
- 根据您的要求更新
interest
字段,现在新添加的字段是interest
interests: {
type: [String]
},
interest: [{
type: Schema.Types.ObjectId,
ref: "interests"
}],
第 2 步:
应用程序中后台使用interests
的地方,使用interest
填充即可
第三步:(只执行查询)
创建兴趣集合并存储个人资料集合中的所有唯一兴趣字符串,因此将聚合查询写入 select 唯一字符串并存储在兴趣集合中,您可以在 mongo 中执行此查询shell 或您在指定原始配置文件集合名称后使用的任何编辑器,
$project
显示兴趣字段只是因为我们要解构它
$unwind
解构interests
数组
$group
by interests and select unique field, and trim white space from interests
string
$project
显示 name
字段,如果你想添加你想要的字段
- $out 将创建一个新集合
interests
并将所有 interests
写入新生成的 _id
字段
db.getCollection('profile').aggregate([
{ $project: { interests: 1 } },
{ $unwind: "$interests" },
{ $group: { _id: { $trim: { input: "$interests" } } } },
{ $project: { _id: 0, name: "$_id" } },
{ $out: "interests" }
])
您有示例输入:
[
{
"_id": 1,
"interests": ["sports","sing","read"]
},
{
"_id": 2,
"interests": ["tracking","travel"]
}
]
执行上述查询后,interests
/新集合中的 output/result 将类似于:
[
{
"_id": ObjectId("5a934e000102030405000000"),
"name": "travel"
},
{
"_id": ObjectId("5a934e000102030405000001"),
"name": "sports"
},
{
"_id": ObjectId("5a934e000102030405000002"),
"name": "read"
},
{
"_id": ObjectId("5a934e000102030405000003"),
"name": "tracking"
},
{
"_id": ObjectId("5a934e000102030405000004"),
"name": "sing"
}
]
第四步:(只执行查询)
在配置文件集合中添加参考 _id
s 来自 interests
集合的新字段兴趣,有执行查询的顺序,
- 当
interest
(新字段)字段不存在时,仅查找配置文件查询和项目必填字段_id
和interests
并迭代使用 forEach
循环
- trim
interests
字符串遍历映射
- 通过创建的
interests
集合 的 name
字段找到 interests
引用 _id
- 更新查询以添加
interest
个在配置文件集合中具有 _id
的字段
db.getCollection('profile').find(
{ interest: { $exists: false } },
{ _id: 1, interests: 1 }).forEach(function(profileDoc) {
// TRIM INTEREST STRING
var interests = profileDoc.interests.map(function(i){
return i.trim();
});
// FIND INTERESTS IDs
var interest = [];
db.getCollection('interests').find(
{ name: { $in: interests } },
{ _id: 1 }).forEach(function(interestDoc){
interest.push(interestDoc._id);
});
// UPDATE IDS IN PROFILE DOC
db.getCollection('profile').updateOne(
{ _id: profileDoc._id },
{ $set: { interest: interest } }
);
});
您有示例输入:
[
{
"_id": 1,
"interests": ["sports","sing","read"]
},
{
"_id": 2,
"interests": ["tracking","travel"]
}
]
执行上述查询后,您的个人资料集合中的结果将类似于:
[
{
"_id": 1,
"interests": ["sports","sing","read"],
"interest": [
ObjectId("5a934e000102030405000001"),
ObjectId("5a934e000102030405000002"),
ObjectId("5a934e000102030405000004")
]
},
{
"_id": 2,
"interests": ["tracking","travel"],
"interest": [
ObjectId("5a934e000102030405000000"),
ObjectId("5a934e000102030405000003")
]
}
]
第 5 步:
现在你已经完成了所有的步骤并且你新添加了interest
字段
并且旧字段 interests
字段仍处于安全模式,只需确保一切正常即可删除旧 interests
字段,
- 从所有配置文件中删除旧字段
interests
字段
db.getCollection('profile').updateMany(
{ interests: { $exists: true } },
{ $unset: { "interests": 1 } }
);
Warning:
- Test this steps in your local/development server before executing in production server.
- Take backup of your database collections before executing queries.
- Field and schema names are predicted you can replace with your original name.
我有一个 Profile
模型,其中包含此字段:
interests: {
type: [String],
},
我的应用 运行 已经有一段时间了。所以这意味着对于几个文档,这个字段已经填充了一个字符串数组。
为了实现某些目标,我需要创建一个带有字段 name
的模型 Interest
,然后在 Profile
中引用它,如下所示:
interests: [{
type: Schema.Types.ObjectId,
ref: "interests",
}],
字段 name
应包含 Profile.interests
中已经存在的 string
个兴趣。
这是我认为我会遵循的方法:
- 创建
Interest
模型。 - 用现有的
Profile.interests
个字符串填充name
字段。
一种。执行此操作时,将Profile.interests
替换为新创建的Interest
文档的_ids
。
b.确保Interest.name
是唯一的。
C。删除空格。 - 应用中后台使用
interests
的地方,用populate
填充。
感觉这不是一个安全的操作。所以我想听听您对此的看法。有更好的方法吗?我应该避免这样做吗?
谢谢。
第 1 步:
- 为兴趣创建模型,
- 根据兴趣架构指定所需字段并为特定字段设置属性
- 根据您的要求在选项中指定集合名称
- 创建模型并在模型中指定您想要的名称
const InterestsSchema = new mongoose.Schema(
{ name: { type: String } },
{ collection: "interests" }
);
const Interests = mongoose.model("Interests", InterestsSchema);
- 而不是删除
interests
字段添加新字段interest
(您可以选择所需的字段),为了安全起见,只要您觉得当前更新有效正确地你可以删除它,更新配置文件架构,
- 根据您的要求更新
interest
字段,现在新添加的字段是interest
interests: {
type: [String]
},
interest: [{
type: Schema.Types.ObjectId,
ref: "interests"
}],
第 2 步:
应用程序中后台使用interests
的地方,使用interest
填充即可
第三步:(只执行查询)
创建兴趣集合并存储个人资料集合中的所有唯一兴趣字符串,因此将聚合查询写入 select 唯一字符串并存储在兴趣集合中,您可以在 mongo 中执行此查询shell 或您在指定原始配置文件集合名称后使用的任何编辑器,
$project
显示兴趣字段只是因为我们要解构它$unwind
解构interests
数组$group
by interests and select unique field, and trim white space frominterests
string$project
显示name
字段,如果你想添加你想要的字段- $out 将创建一个新集合
interests
并将所有interests
写入新生成的_id
字段
db.getCollection('profile').aggregate([
{ $project: { interests: 1 } },
{ $unwind: "$interests" },
{ $group: { _id: { $trim: { input: "$interests" } } } },
{ $project: { _id: 0, name: "$_id" } },
{ $out: "interests" }
])
您有示例输入:
[
{
"_id": 1,
"interests": ["sports","sing","read"]
},
{
"_id": 2,
"interests": ["tracking","travel"]
}
]
执行上述查询后,interests
/新集合中的 output/result 将类似于:
[
{
"_id": ObjectId("5a934e000102030405000000"),
"name": "travel"
},
{
"_id": ObjectId("5a934e000102030405000001"),
"name": "sports"
},
{
"_id": ObjectId("5a934e000102030405000002"),
"name": "read"
},
{
"_id": ObjectId("5a934e000102030405000003"),
"name": "tracking"
},
{
"_id": ObjectId("5a934e000102030405000004"),
"name": "sing"
}
]
第四步:(只执行查询)
在配置文件集合中添加参考 _id
s 来自 interests
集合的新字段兴趣,有执行查询的顺序,
- 当
interest
(新字段)字段不存在时,仅查找配置文件查询和项目必填字段_id
和interests
并迭代使用forEach
循环
- trim
interests
字符串遍历映射 - 通过创建的
interests
集合 的 - 更新查询以添加
interest
个在配置文件集合中具有_id
的字段
name
字段找到 interests
引用 _id
db.getCollection('profile').find(
{ interest: { $exists: false } },
{ _id: 1, interests: 1 }).forEach(function(profileDoc) {
// TRIM INTEREST STRING
var interests = profileDoc.interests.map(function(i){
return i.trim();
});
// FIND INTERESTS IDs
var interest = [];
db.getCollection('interests').find(
{ name: { $in: interests } },
{ _id: 1 }).forEach(function(interestDoc){
interest.push(interestDoc._id);
});
// UPDATE IDS IN PROFILE DOC
db.getCollection('profile').updateOne(
{ _id: profileDoc._id },
{ $set: { interest: interest } }
);
});
您有示例输入:
[
{
"_id": 1,
"interests": ["sports","sing","read"]
},
{
"_id": 2,
"interests": ["tracking","travel"]
}
]
执行上述查询后,您的个人资料集合中的结果将类似于:
[
{
"_id": 1,
"interests": ["sports","sing","read"],
"interest": [
ObjectId("5a934e000102030405000001"),
ObjectId("5a934e000102030405000002"),
ObjectId("5a934e000102030405000004")
]
},
{
"_id": 2,
"interests": ["tracking","travel"],
"interest": [
ObjectId("5a934e000102030405000000"),
ObjectId("5a934e000102030405000003")
]
}
]
第 5 步:
现在你已经完成了所有的步骤并且你新添加了interest
字段
并且旧字段 interests
字段仍处于安全模式,只需确保一切正常即可删除旧 interests
字段,
- 从所有配置文件中删除旧字段
interests
字段
db.getCollection('profile').updateMany(
{ interests: { $exists: true } },
{ $unset: { "interests": 1 } }
);
Warning:
- Test this steps in your local/development server before executing in production server.
- Take backup of your database collections before executing queries.
- Field and schema names are predicted you can replace with your original name.