mongo实现数据查询的自比较

本文介绍在MongoDB中如何利用$expr和$where进行字段间的比较查询,包括在不同版本下的使用方法及性能对比,特别强调了3.6版本以上$expr的高效性和对count函数的支持。

需求是这样的,我想要在一个集合中查询出我需要的数据,约束条件中,这条数据的某个字段的值与自身的另外一个字段数据进行比较,满足判断等式的数据返回。

对应的SQL

select count(1) from hello where field1>field2

如果是老司机知道如何查询的话,那就不用往下看了!

$where

在mongo3.6以下可以使用$where来达到目的,对应的写法是 

db.hello.find({$where:'this.field1>this.field2'})
db.hello.find({$where:function(){return this.field1>this.field2}})

需要注意的是$where​​​​​​​本身不能使用count,会报错 $where​​​​​​​is not allowed in this context,此处上下文不允许使用 $where​​​​​​​,如果要达到统计多少条的目的,查询出来之后,判断长度,可以在options选项中设置只返回的_id以减少传输的数据量,提高查询效率。

db.hello.find({$where:'this.field1>this.field2'},{_id:1})
db.hello.find({$where:function(){return this.field1>this.field2}},{_id:1})

一个非常大的问题是$where​​​​​​​本身是逐条执行js语句,this就是游标指向的当前行。那么问题来了$where​​​​​​​​​​​​​​会不会走组合索引了?如果我在field1,field2上建立一个联合索引,那么使用$where​​​​​​​会不会走索引了?个人猜测是会的

$expr

在mongo3.6版本以上,可以使用这个$expr。效率高于$where,原因在于不执行js语句。另外$expr不支持多键索引,mongo在建议索引时,如果你的字段类型是数组,那么mongo会为数组中的每个元素建立索引,这样的索引称为多建索引。对于的具体查询语句是

db.hello.find({$expr:{$gt:['$field1','$field2']}}).count()        

使用$expr是支持count函数的。除此以外,还可以对字段带条件的处理。$expr

db.supplies.find( {
    $expr: {
       $lt:[ {
          $cond: {
             if: { $gte: ["$qty", 100] },
             then: { $divide: ["$price", 2] },
             else: { $divide: ["$price", 4] }
           }
       },
       5 ] }
} )

 

实现 MongoDB 数据的增量同步通常涉及以下几个关键步骤:识别增量数据、提取变更数据、传输数据以及在目标系统中应用变更。Apache NiFi 提供了多种处理器和功能,可以有效地完成这些任务。以下是使用 Apache NiFi 实现 MongoDB 数据增量同步的详细方案。 ### ### 使用 MongoDB Change Streams 实现增量同步 MongoDB 从 3.6 版本开始引入了 **Change Streams** 功能,允许应用程序实时订阅数据库、集合或部署级别的数据变更事件。这一特性非常适合用于实现增量同步。 NiFi 提供了 `ConsumeMongoChangeStream` 处理器,可以监听 MongoDB 的变更流,并将变更事件作为 FlowFile 发送至下游处理器。该处理器支持以下配置: - **MongoDB URI**:连接 MongoDB 的 URI。 - **Database Name** 和 **Collection Name**:指定监听的数据库和集合。 - **Batch Size**:每次拉取的变更记录数量。 - **Polling Interval**:轮询变更流的时间间隔。 ```xml <processor name="ConsumeMongoChangeStream" class="org.apache.nifi.processors.mongodb.ConsumeMongoChangeStream"> <property name="MongoDB URI" value="mongodb://localhost:27017"/> <property name="Database Name" value="testdb"/> <property name="Collection Name" value="testcollection"/> <property name="Polling Interval" value="5 sec"/> </processor> ``` ### ### 使用时间戳字段进行增量拉取 如果 MongoDB 数据集中存在一个表示最后修改时间的字段(例如 `last_modified`),可以通过定期查询该字段大于上次同步时间戳的文档来实现增量同步。 NiFi 的 `ExecuteMongoQuery` 处理器可以执行自定义的 MongoDB 查询语句。通过结合 `UpdateAttribute` 和 `QueryMongoDB`,可以实现基于时间戳的增量同步流程。 ```xml <processor name="QueryMongoDB" class="org.apache.nifi.processors.mongodb.QueryMongoDB"> <property name="MongoDB URI" value="mongodb://localhost:27017"/> <property name="Database Name" value="testdb"/> <property name="Collection Name" value="testcollection"/> <property name="Query" value="{ 'last_modified': { '$gt': '${last_sync_time}' } }"/> </processor> ``` ### ### 数据传输与目标系统写入 一旦获取到增量数据,可以使用 NiFi 的其他处理器将数据写入目标系统。例如: - 使用 `PutHiveQL` 将数据写入 Hive。 - 使用 `PutKafka` 将数据发送到 Kafka 主题。 - 使用 `PutMongoRecord` 将数据写入另一个 MongoDB 实例。 若目标为 Hive,由于 Hive 通常使用 ORC 格式存储数据,而 MongoDB 输出为 JSON 格式,需进行格式转换。NiFi 提供了 `ConvertRecord` 处理器,可将 JSON 转换为 Avro,再通过 `ConvertAvroToORC` 转换为 ORC 格式[^2]。 ### ### 状态管理与持久化 为确保同步过程的连续性,NiFi 支持状态管理机制。使用 `UpdateAttribute` 和 `FetchAttribute` 可以持久化上次同步的时间戳或变更流的 token,从而在下次同步时继续从上次的位置开始处理。 ```xml <processor name="UpdateAttribute" class="org.apache.nifi.processors.attributes.UpdateAttribute"> <property name="last_sync_time" value="${now():format('yyyy-MM-dd HH:mm:ss')}"/> </processor> ``` ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值