MongoDB 4.2亮点功能之——管道更新功能和查询功能

使用MongoDB时,如果需要比增、删、改、查操作更复杂的功能,过去我们会求助于聚合框架,装配出功能强大的操作管道,执行文档转换功能。在MongoDB 4.2中,管道功能被引入了update命令,使该命令的功能得到了极大提升。我们将向你介绍该命令的工作方式,再介绍新的聚合运算符以及4.2版本中的表达式,为你提供更多选项——三角函数、正则表达式和当前时间。

无处不在的管道

在何处使用聚合管道的问题现在已经发生了重大转变。以前,管道和aggregate 函数捆绑在一起。通过4.2版本,你还可以立即着手创建和使用管道,作为update和findAndModify命令的一部分。我们可以通过一个例子来说明这种改变。首先,让我们创建一个文档:

过去,如果我们想获取val1和val2的total(合计值),由于无法引用经过更新的字段,我们只能获取该文档,将两个变量相加,然后更新文档。

当然,这里包含了一次往返式的操作,如果不是为了举例的话,它可能是其他更新操作的一部分。聪明的MongoDB用户可能永远不会计算合计值并保存它,他们知道聚合管道有一个$sum运算符。它可以将值数组加进来,并使用$ notation引用相应字段,如下所示:

这个操作并未将数据持久化:

现在的情况是,这条聚合命令会处理整个集合的数据。我们需要增加一个$match执行阶段,将它的作用域设置到一个文档中…

只要我们能将聚合框架的功能带入update命令,就能解决这个问题。在MongoDB 4.2中,我们可以这样操作:

将聚合管道移入我们的更新命令,我们选定的文档就发生了相应变化。如果我们设定一个字段值,它就会被写入文档。这些全部发生在服务器上,没有数据往返的情况。它包含聚合框架的功能,可以在服务器上执行一个条件语句,如下所示:

对语句格式做一下修改,这样看起来更清楚一些:

这是MongoDB开发人员持续性任务的一部分,将查询语言和聚合操作统一起来,在每一处提供相同的功能。当谈到聚合框架中的改进之处时,还包括了使用聚合管道时用到的update和findAndModify命令。

如果你熟悉聚合框架,很有可能你想知道$set聚合执行阶段来自何处。在4.2版本中,它是一项新功能,但又不算太新;它是原有$addFields执行阶段的别名,设计它是为了实现语言的无缝统一。它是三个适用于更新操作的聚合执行阶段中的一个。每个阶段都有一个新的别名,连同原来聚合阶段的名称,如下所示:

- $set/$addFields

$unset/$project

$replaceWith/$replaceRoot

这些执行阶段允许你添加、移除字段或完全替换整个文档;在你更新文档时,可以完成你想要的所有操作。

平滑算子

在MongoDB 4.2推出之前,通用的三角函数计算功能是缺失的几项功能之一。在MongoDB 4.2中,一整套三角函数表达式被添加到聚合框架中,避免了功能缺失的风险。用$sin, $cos, $tan, $asin, $acos, $atan, $atan2, $asinh, $acosh和$atanh可以支持sin, cos, tan和它们的反函数以及反双曲线变量。所有这些表达式都接受弧度值,因此也支持$degreesToRadians和$radiansToDegrees这种换算表达式。

还有一种新设计的$round表达式,可以对数值做四舍五入处理,保留特定的整数和小数位。请注意,原来用于将数值截短为整数的$trunc表达式这一功能已经升级了,现在可以将数值截短,保留特定的整数和小数位,但该函数在使用旧的语法时还保留着过去的行为。

我们将所有这些函数一起放在一个查询实例中,仍然使用前面用过的文档:

我们得到val1的sine值,然后做四舍五入处理,并保留5位小数,将结果写回到文档,用作新的sin字段。

适用所有情况的正则表达式

MongoDB 4.2之前,你只能在聚合的$match执行阶段使用$regex运算符。这意味着,以前你只能将其用于匹配操作,而不能用于解析和抽取部分字符串。有了4.2版本,一切都改变了,有了三个新的运算符:$regexFind, $regexFindAll和$regexMatch。让我们演示一个简单的例子。首先,我们将一些字符串扔到文档中:

现在,我们希望捕获这段词组中出现的数字,但只捕获那些后面是numbers或digits的数字。我们使用([0-9]+) (numbers|digits)作为表达式。这个表达式获取的数字后跟的是正则表达式圆括弧中的单词。现在,我们在聚合中运行个表达式,查看得到的结果:

如果查看结果字段,我们会发现,取回的不仅仅是简单的是或否的匹配结果:

这里我们会看到返回的match字段,为我们提供了正确的字符串,这是由正则表达式工具匹配得出的。Idx字段表示该匹配结果距离源字符串开始的位置。最后,捕获数组返回的是匹配字符串的每个被捕获的部分——第一个元素是字符串中的数字,第二个元素是单词“numbers”或“digits”。对复杂的字符串解析工作来说,这个结果很理想。如果没有匹配上,$regexFind就会返回一个空值(null)。

使用$regexFind,你只能得到第一个匹配结果,并将它捕获回来。如果你找到了很多的匹配结果,接着使用$regexFindAll,就可以将所有匹配模式抽取到一个结果数组中,类似从$regexFind得到的结果。在这种情况下,如果没有匹配结果,就会返回一个空数组。

如果你想要的只是一个是或否的结果,即是否有结果与正则表达式相匹配,那么,使用$regexMatch就可以做到。

终于有了$$NOW

很多人想把时间戳嵌入到他们的文档中,而不需要反复回到客户端去获取文档时间。在4.2版本中,包含了$$NOW,这是一个在聚合管道中可以访问的变量,它返回的是用ISODate格式表示的当前时间。

在下一部分,我们将探讨按需式物化视图,其中用到了很多本文中探讨的功能。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20190828A0QWVR00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券