- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
集合中的示例文档:
{ "teamAlpha": { }, "teamBeta": { }, "leader_name": "leader"}
对于此类文档,我想删除所有以 "team"
开头的字段。所以预期的结果是
{leader_name: "领导者"}
我当前正在使用一个函数:
db.teamList.find().forEach(
function(document) {
for(var k in document) {
if (k.startsWith('team')) {
delete document[k];
}
}
db.teamList.save(document);
}
);
我想知道是否有更好的方法来解决这个问题。
最佳答案
提前确定所有可能的键然后发出单个 "multi"
会“更好”更新以删除所有 key 。根据可用的 MongoDB 版本,会有不同的方法。
let fields = db.teamList.aggregate([
{ "$project": {
"_id": 0,
"fields": {
"$map": {
"input": {
"$filter": {
"input": { "$objectToArray": "$$ROOT" },
"as": "d",
"cond": { "$eq": [{ "$substrCP": [ "$$d.k", 0, 4 ] }, "team" ] }
}
},
"as": "f",
"in": "$$f.k"
}
}
}},
{ "$unwind": "$fields" },
{ "$group": { "_id": "$fields" } }
])
.map( d => ({ [d._id]: "" }))
.reduce((acc,curr) => Object.assign(acc,curr),{})
db.teamList.updateMany({},{ "$unset": fields });
.aggregate()
语句通过 $objectToArray
将文档中的字段转换为数组,然后应用 $filter
仅返回“key”的前四个字母与字符串“team”匹配的内容。然后用 $unwind
进行处理和 $group
制作匹配字段的“唯一列表”。
后续指令仅将游标中返回的列表处理为单个对象,例如:
{
"teamBeta" : "",
"teamAlpha" : ""
}
然后将其传递给 $unset
从所有文档中删除这些字段。
var fields = db.teamList.mapReduce(
function() {
Object.keys(this).filter( k => /^team/.test(k) )
.forEach( k => emit(k,1) );
},
function() {},
{ "out": { "inline": 1 } }
)
.results.map( d => ({ [d._id]: "" }))
.reduce((acc,curr) => Object.assign(acc,curr),{})
db.teamList.update({},{ "$unset": fields },{ "multi": true });
基本相同,唯一的区别在于 .updateMany()
不存在作为我们简单调用 .update()
的方法使用"multi"
parameter应用于所有匹配的文档。这就是新 API 调用实际执行的全部操作。
仅仅为了删除字段而迭代所有文档当然是不明智的,因此上述任一方法都是“首选”方法。唯一可能的失败是构建 key 的“不同列表”实际上超出了 16MB BSON 限制。这是相当极端的,但根据实际数据,这是可能的。
因此,本质上有“两个扩展”自然适用于这些技术:
将“光标”与.aggregate()一起使用
var fields = [];
db.teamList.aggregate([
{ "$project": {
"_id": 0,
"fields": {
"$map": {
"input": {
"$filter": {
"input": { "$objectToArray": "$$ROOT" },
"as": "d",
"cond": { "$eq": [{ "$substrCP": [ "$$d.k", 0, 4 ] }, "team" ] }
}
},
"as": "f",
"in": "$$f.k"
}
}
}},
{ "$unwind": "$fields" },
{ "$group": { "_id": "$fields" } }
]).forEach( d => {
fields.push(d._id);
if ( fields.length >= 2000 ) {
db.teamList.updateMany({},
{ "$unset":
fields.reduce((acc,curr) => Object.assign(acc,{ [curr]: "" }),{})
}
);
}
});
if ( fields.length > 0 ) {
db.teamList.updateMany({},
{ "$unset":
fields.reduce((acc,curr) => Object.assign(acc,{ [curr]: "" }),{})
}
);
}
这实际上会将“光标”上处理的字段数量“批处理”为 2000 个,这“应该”远低于请求的 16MB BSON 限制。
通过 mapReduce() 使用临时集合
db.teamList.mapReduce(
function() {
Object.keys(this).filter( k => /^team/.test(k) )
.forEach( k => emit(k,1) );
},
function() {},
{ "out": { "replace": "tempoutput" } }
);
db.tempoutput.find({},{ "_id": 1 }).forEach(d => {
fields.push(d._id);
if ( fields.length >= 2000 ) {
db.teamList.update({},
{ "$unset":
fields.reduce((acc,curr) => Object.assign(acc,{ [curr]: "" }),{})
},
{ "multi": true }
);
}
});
if ( fields.length > 0 ) {
db.teamList.update({},
{ "$unset":
fields.reduce((acc,curr) => Object.assign(acc,{ [curr]: "" }),{})
},
{ "multi": true }
);
}
本质上又是相同的过程,除了 mapReduce
无法输出到“光标”,您需要输出到仅包含“不同字段名称”的临时集合,然后进行迭代该集合中的光标,以便以相同的“批处理”方式进行处理。
正如类似的初始方法一样,这些选项比迭代整个集合并单独对每个文档进行调整要高效得多。通常没有必要这样做,因为任何“不同列表”实际上导致单个更新请求超过 16MB 的可能性确实非常大。但这将再次成为处理这种极端情况的“首选”方式。
当然,如果您只是知道所有字段名称,并且不需要通过检查集合来计算出它们,那么只需用已知名称编写语句即可:
db.teamList.update({},{ "$unset": { "teamBeta": "", "teamAlpha": "" } },{ "multi": true })
这是完全有效的,因为所有其他语句正在做的就是计算出这些名称应该适合您。
关于javascript - 删除所有以名称 "XX"开头的字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45472583/
我住在荷兰,货币是用逗号 (,) 而不是点 (.)即 14.95 的 feeds 被解释为数字而不是 14.95 欧元 有没有可以解决这个问题的LINUX命令(sed?)?所以14.95变成了14,9
我想问: 我有两个表employee,其中包含字段ID、Fullname、email...和表task 包含字段 name_task、list_employee... 使用字段list_employe
请看下面的测试数据。我想获取 avgtime (=timeonsite/visits) 并在 mysql 中显示为“xx:xx:xx”结果。我怎样才能得到它? SET FOREIGN_KEY_CHEC
我必须处理一个大文件(几 MB)并从中删除带有时间标记的注释。一个例子: blablabla 12:10:40 I want to remove this blablabla some more e
所以我有这些数据直接从 iTunes 复制/粘贴: Excel 具有“XX:XX:00”格式,即“hh:mm:ss”,但您可以想象,它更像“mm:ss:00”。音乐时间不长! 由于这不是直接的单元格格
我有一个对象列表,我想使用 Option.Numero_Reference 属性对其进行排序。 Numero_reference 是一个 xx.xx.xx 格式的字符串 有没有办法按 xx 组排序?
我正在尝试部署 nginx - ingress kubectl run nginx --image=nginx kubectl get pod NAME
我有一个日期“2014-07-02 20:57:38 +0000”,我想将它的格式设置为“今天晚上 8:57”。我希望如果一个字符串是昨天,则将其显示为“昨天上午 9:00”。如果既不是今天也不是昨天
目前我使用的是Apache http components client V4.3.5。在我的例子中,我可以上传小文件(1kb),但是当我运行代码并得到异常“org.apache.http.NoHtt
我在 Linux (RHEL 7) 中运行 HTTPS 服务器。我一启动服务器就收到以下错误。 2019/09/04 15:46:16 http: TLS handshake error from x
我正在参加 CTF 挑战赛,该挑战赛有一个链接,如下所示:46.XXX.XX.XX:8008/ 如果我打开该页面中的开发者工具,我可以找到一个小程序,其属性代码值为“mPage.class”
你好 我想每隔 X 小时在我的程序中运行一个方法,该怎么做?我正在谷歌搜索,但什么也没有:/ 最佳答案 你可以考虑Quartz . 它是在 java 中运行的某种 cron。不过我承认,如果您只想安排
我正在尝试检查 NSString 是否为特定格式。 日:日:日。我在想 NSRegularExpression。有点像 /^(\d)\d:\d\d:\d\d)$/? 最佳答案 你有没有试过这样的事情:
我收到错误 git 存储库的 RSA 主机 key 不在已知主机列表中。当我使用存储库 URL 作为我的 git 克隆 URL 运行 jenkins 作业时。 我尝试在运行作业的主机中克隆相同的存储库
我有一个计数器,每 1 秒计数一次,并将 1 添加到 int。 问题 如何格式化我的字符串,使计数器看起来像这样: 00:01:23 代替: 123 我尝试过的事情 到目前为止我尝试过的事情: for
ERROR 2003 (HY000): Can't connect to MySQL server on 'xx.xx.xx.xx.' (60) 我在尝试远程连接到此服务器时收到此错误。我最近硬重启了
我正在尝试将一些数据从客户端浏览器插入到 AWS 服务器上的 MySQL 数据库。 该代码在 godaddy 上运行,因此看起来像是权限/安全问题。 $servername = "xx.xx.xx.x
我想知道是否有标准方法可以以“UTC+XX:XX”或“UTC-XX:XX”格式返回设备的当前时区? 基于格式化 NSDate 我知道可以在“ZZZZ”的帮助下获得当前时区,它给出“GMT-08:00”
我的 JVM 有 -server 选项,我相信它使 JVM 能够使用 C2 编译器,这意味着用于服务器应用程序,这些应用程序往往比客户端应用程序运行时间更长。但是,GRAAL JIT(由 -XX:+U
public void colortemperatureJSliderStateChanged(ChangeEvent event) { fahrenheitdegree = colortemp
我是一名优秀的程序员,十分优秀!