mongodb - MongoDB $set 合计
问题描述
我想根据另一个“源”集合的文档中的字段值,在“目标”集合的每个文档中设置一个新字段的值。
目标集合的文档如下所示:
数据库名称:
{
"name" : "Larry",
"info" : {
"phone" : "5551212"
}
}
{
"name" : "Curly",
"info" : {
"phone" : "5551213"
}
}
{
"name" : "Moe",
"info" : {
"phone" : "5551234"
}
}
第二个集合的文档如下所示(我希望将此时区添加到目标集合中):
db.phones:
{
"phone" : "5551212",
"timezone" : "UTC-6"
}
{
"phone" : "5551213",
"timezone" : "UTC-7"
}
{
"phone" : "5551234",
"timezone" : "UTC-6"
}
我希望第一个“目的地”集合的文档最终看起来像这样:
数据库名称:
{
"name" : "Larry",
"info" : {
"phone" : "5551212",
"timezone" : "UTC-6"
}
}
{
"name" : "Curly",
"info" : {
"phone" : "5551213",
"timezone" : "UTC-7"
}
}
{
"name" : "Moe",
"info" : {
"phone" : "5551234",
"timezone" : "UTC-6"
}
}
换句话说,我有一个包含时区的非常大的集合(电话)和一个不包含时区的非常大的集合(名称),我希望第一个集合包含这些时区,并使用两者中的电话号码作为键。
我在 mongoShell 中尝试过,但没有成功:
list = db.names.aggregate([
{ $match: { } },
{ $lookup: {
from: "phones",
localField: "info.phone",
foreignField: "phone",
as: "zoneinfo"
}
}
]);
list.result.forEach(function(x) {
db.names.update({_id:x._id}, {$set:{'info.timezone':'zoneinfo.timezone'}});
});
因此,链接时区集合并将其添加到list
结果中,作为每个文档的新字段(这很有效)。然后,由于我们无法在 中进行更新aggregate
,因此迭代生成的文档,从之前操作中添加info.timezone
的“临时”字段 中添加一个新的永久字段 。zoneinfo.timezone
我在这里做错了什么?还有其他更好的方法吗?每个集合中有数千个文档,因此手工工作是不可取的。
解决方案
您需要记住的一件事是$lookup作为数组返回zoneInfo
,因此为了使用该字段,您需要对其运行$unwind。然后,您可以使用$addFields和$project简单地重塑您的文档。尝试:
db.names.aggregate([
{
$lookup: {
from: "phones",
localField: "info.phone",
foreignField: "phone",
as: "phoneDetails"
}
},
{
$unwind: "$phoneDetails"
},
{
$addFields: {
"info.timezone": "$phoneDetails.timezone"
}
},
{
$project: {
phoneDetails: 0
}
}
])
如果要更新现有集合,可以在最后一步添加$out 。
推荐阅读
- html - 我收到这个 HMR 正在等待来自 WDS 的更新信号……但没有显示?
- javascript - 使用 jQuery 获取对象内部的内容
- php - Laravel cookie 未在浏览器中设置
- javascript - 如何在不使用绝对位置的情况下从右侧阻止 div 的宽度扩展?
- java - io.cucumber.junit.UndefinedStepException
- python - 在 Python 中将套接字发送到 Wi-Fi 控制器
- javascript - 如何在vue3中创建vnode直接注入到父节点
- python-3.x - 使用 rumael.yaml 合并两个 yaml 文件
- python - SQLAlchemy,需要帮助理解 scoped_session
- python - Pygame 输入框