MongoDB位运算基本使用以及位运算应用场景

最近在公司业务上用到了二进制匹配数据,但是MongoDB进行二进制运算(Bitwise)没用过,网上博客文章少,所以就上官网看API,因此记录一下,顺便在普及一下使用二进制位运算的一些应用。

在MongoDB的V3.2版本以后才支持的位运算,在这个版本之前是不支持,所以想要用位运算,需先将MongoDB的版本升级至V3.2。

说明

查询操作

在官方文档中,在查询操作中共支持四种位运算方法,官方文档链接

$bitsAllClear所有指定二进制的位数都为0
$bitsAllSet所有指定二进制的位数都为1
$bitsAnyClear任意一位指定二进制的位数为0
$bitsAnySet任意一位指定二进制的位数为1

这个指定的位数是不是有点难以理解

例如255这个数字的二进制有8位,那么位数则是position指定的位置,Integer的最大值为2的31次方,那么指定的位置(position)最大为31位

bit11111111
position76543210

更新操作

使用$bit进行更新操作,支持and|or|xor 三种位运算符 即对应位运算符的  &(与) 、|(或) 、~(异或)

将指定列的值(field)通过指定的位运算计算出的结果更新至数据库中,下面有示例

更新语法如下:

{ $bit: { <field>: { <and|or|xor>: <int> } } }

位运算的使用

查询操作

在MongoDB数据库中user集合的数据为:

{ "_id" : "03ddb005-6e8e-45b9-be74-9c840f925f1f", "name" : "Tomcar", "bitData" : NumberLong(100), "_class" : "com.mongodb.mongo_test.bean.User" }
{ "_id" : "dccb1549-bbaf-438b-9c52-dd9549de6fde", "name" : "Java", "bitData" : NumberLong(20), "_class" : "com.mongodb.mongo_test.bean.User" }
{ "_id" : "1bcf44ba-92ee-4dda-ae1b-4b0b28816fc1", "name" : "python", "bitData" : NumberLong(131), "_class" : "com.mongodb.mongo_test.bean.User" }
{ "_id" : "50b76890-d533-4455-8a13-fce98bbd96fe", "name" : "php", "bitData" : NumberLong(8), "_class" : "com.mongodb.mongo_test.bean.User" }

二进制对应

1000110 0100
200001 0100
1311000 0011
80000 1000

$bitsAllSet

执行命令:

db.user.find({"bitData":{$bitsAllSet:[1,4]}}) //将二进制的第2位以及第5位上为1的匹配出来

 结果:

{ "_id" : "1bcf44ba-92ee-4dda-ae1b-4b0b28816fc1", "name" : "python", "bitData" : NumberLong(131), "_class" : "com.mongodb.mongo_test.bean.User" }

$bitsAllClear

执行命令:

db.user.find({"bitData":{$bitsAllClear:[1,4]}}); //将二进制的第2位以及第5位上为0的匹配出来

结果:

{ "_id" : "03ddb005-6e8e-45b9-be74-9c840f925f1f", "name" : "Tomcar", "bitData" : NumberLong(100), "_class" : "com.mongodb.mongo_test.bean.User" }
{ "_id" : "50b76890-d533-4455-8a13-fce98bbd96fe", "name" : "php", "bitData" : NumberLong(8), "_class" : "com.mongodb.mongo_test.bean.User" }

 $bitsAnyClear

执行命令:

db.user.find({"bitData":{$bitsAnyClear:[1,4]}}); //将第2位或者第5位上为0的查询出来

结果:

{ "_id" : "03ddb005-6e8e-45b9-be74-9c840f925f1f", "name" : "Tomcar", "bitData" : NumberLong(100), "_class" : "com.mongodb.mongo_test.bean.User" }
{ "_id" : "dccb1549-bbaf-438b-9c52-dd9549de6fde", "name" : "Java", "bitData" : NumberLong(20), "_class" : "com.mongodb.mongo_test.bean.User" }
{ "_id" : "1bcf44ba-92ee-4dda-ae1b-4b0b28816fc1", "name" : "python", "bitData" : NumberLong(131), "_class" : "com.mongodb.mongo_test.bean.User" }
{ "_id" : "50b76890-d533-4455-8a13-fce98bbd96fe", "name" : "php", "bitData" : NumberLong(8), "_class" : "com.mongodb.mongo_test.bean.User" }

 $bitsAnySet

执行命令:

db.user.find({"bitData":{$bitsAnySet:[1,4]}}); //将第2位或者第5位上为1的查询出来

结果:

{ "_id" : "dccb1549-bbaf-438b-9c52-dd9549de6fde", "name" : "Java", "bitData" : NumberLong(20), "_class" : "com.mongodb.mongo_test.bean.User" }
{ "_id" : "1bcf44ba-92ee-4dda-ae1b-4b0b28816fc1", "name" : "python", "bitData" : NumberLong(131), "_class" : "com.mongodb.mongo_test.bean.User" }

通过数字进行位运算

如果不是用过指定位数进行运算的话,而是指定数字进行的话,查询结果$bitsAllClear与$bitsAnyClear一致;$bitsAllSet与$bitsAnySet一致。

示例:

命令:
db.user.find({"bitData":{$bitsAnySet:4}})
结果:
{ "_id" : "03ddb005-6e8e-45b9-be74-9c840f925f1f", "name" : "Tomcar", "bitData" : NumberLong(100), "_class" : "com.mongodb.mongo_test.bean.User" }
{ "_id" : "dccb1549-bbaf-438b-9c52-dd9549de6fde", "name" : "Java", "bitData" : NumberLong(20), "_class" : "com.mongodb.mongo_test.bean.User" }命令:
db.user.find({"bitData":{$bitsAnyClear:4}})
结果:
{ "_id" : "1bcf44ba-92ee-4dda-ae1b-4b0b28816fc1", "name" : "python", "bitData" : NumberLong(131), "_class" : "com.mongodb.mongo_test.bean.User" }
{ "_id" : "50b76890-d533-4455-8a13-fce98bbd96fe", "name" : "php", "bitData" : NumberLong(8), "_class" : "com.mongodb.mongo_test.bean.User" }

大家可以各自去试一下。

更新操作

在命令中指定更新某个ID的bitData列,当前列数据为8,这里通过使用与(&)运算做示例:

db.user.update({"_id":"50b76890-d533-4455-8a13-fce98bbd96fe"},{$bit:{"bitData":{and:NumberLong(4)}}})

结果集:

{ "_id" : "03ddb005-6e8e-45b9-be74-9c840f925f1f", "name" : "Tomcar", "bitData" : NumberLong(100), "_class" : "com.mongodb.mongo_test.bean.User" }
{ "_id" : "dccb1549-bbaf-438b-9c52-dd9549de6fde", "name" : "Java", "bitData" : NumberLong(20), "_class" : "com.mongodb.mongo_test.bean.User" }
{ "_id" : "1bcf44ba-92ee-4dda-ae1b-4b0b28816fc1", "name" : "python", "bitData" : NumberLong(131), "_class" : "com.mongodb.mongo_test.bean.User" }
{ "_id" : "50b76890-d533-4455-8a13-fce98bbd96fe", "name" : "php", "bitData" : NumberLong(0), "_class" : "com.mongodb.mongo_test.bean.User" }

其他的两个命令也可以各自调试。

在Java代码中使用位运算

查询操作

在Spring Boot封装好的MongoTemplate中带条件查询使用Query以及Criteria配合使用,使用位运算的话需使用Criteria的bits()方法:这些方法对应上面的四个方法

而采用Mongo客户端查询位运算:

	MongoCollection<Document> collection = mongoTemplate.getCollection("user");Document filter = new Document();//0110 0100 100//0001 0100 20//1000 0011 131//0000 1000 8filter.append("bitData", new Document("$bitsAllClear", Arrays.asList(1,4)) );/*** $bitsAllClear 进行位运算并且计算结果为 0 的匹配出来* $bitsAllSet 进行位运算并且计算结果不为 0 的匹配出来* $bitsAnyClear 进行位运算并且计算结果为 0 的匹配出来* $bitsAnySet 进行位运算并且计算结果不为 0 的匹配出来*/FindIterable<Document> iterable = collection.find(filter);MongoCursor<Document> iterator = iterable.iterator();System.out.println("采用Bson形式查询");while(iterator.hasNext()) {Document next = iterator.next();Object object = next.get("bitData");if(object instanceof Long)System.out.println(Long.toBinaryString((Long) object));System.out.println(next);}

 更新操作

在SpringBoot的MongoTemplate的更新操作为:

	Update update = new Update();update.bitwise("bitData").and(2);mongoTemplate.updateFirst(Query.query(Criteria.where("_id").is("50b76890-d533-4455-8a13-fce98bbd96fe")), update, User.class);

 采用mongo的客户端为:

MongoCollection<Document> collection = mongoTemplate.getCollection("user");
collection.updateOne(new Document().append("_id", "50b76890-d533-4455-8a13-fce98bbd96fe"),Updates.bitwiseAnd("bitData", Long.valueOf(4)));

位运算的应用

位运算即使用二进制进行计算,所以这个的计算效率是最快的,先看一下常用使用的位运算

public static void main(Stringa rgs []){//位与  &(1&1=1 1&0=0 0&0=0)
System.out.println("the 4 is "+Integer.toBinaryString(4));
System.out.println("the 6 is "+Integer.toBinaryString(6));
System.out.println("the 4&6 is "+Integer.toBinaryString(4&6));
//位或 | (1|1=1 1|0=1 0|0=0)
System.out.println("the 4|6 is "+Integer.toBinaryString(4|6));
//位非~(~1=0  ~0=1)
System.out.println("the ~4 is "+Integer.toBinaryString(~4));
//位异或 ^ (1^1=0 1^0=1 0^0=0)
System.out.println("the 4^6 is "+Integer.toBinaryString(4^6));
// <<有符号左移 >>有符号的右移  >>>无符号右移
//取模的操作 a % (2^n) 等价于 a&(2^n-1)
System.out.println("the 345 % 16 is "+(345%16)+ " or "+(345&(16-1)));
}

运算结果为:

the 4 is 100
the 4 is 100
the 6 is 110
the 4&6 is 100
the 4|6 is 110
the ~4 is 11111111111111111111111111111011
the 4^6 is 10
the 345 % 16 is 9 or 9

虽然看起来平常开发用不到,但是可以使用到权限这一块由于Integer最大值可以到2的31次方,所以单个数字就可以存储31中权限,不仅仅可以在业务上使用;

在JDK的反射包中有个类Modifier.class,这个类是采集每个Class的中修饰符以及类型。不仅仅是反射在JUC的包中也使用到了这个位运算,因为运算速度快,所以在很多基础框架中用的还是很多的。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/537136.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Mybatis源码日志模块分析

看源码需要先下载源码&#xff0c;可以去Mybatis的github上的仓库进行下载&#xff0c;Mybatis 这次就先整理一下日志这一块的源码分析&#xff0c;这块相对来说比较简单而且这个模块是Mybatis的基础模块。 之前的文章有谈到过Java的日志实现&#xff0c;大家也可以参考一下&…

python手机端给电脑端发送数据_期货交易软件有哪些比较好用?分手机端和电脑端...

一、电脑端交易软件期货电脑端交易软件目前市场上用的最多的是文华财经和博易大师&#xff0c;这两个软件都是免费交易使用的。从投资者使用角度来看&#xff0c;目前电脑端文华财经的评价比博易大师高一些。当然每个投资者有自己的使用习惯&#xff0c;博易大师也有自己优点&a…

Find the Difference(leetcode389)

2019独角兽企业重金招聘Python工程师标准>>> Given two strings s and t which consist of only lowercase letters. String t is generated by random shuffling string s and then add one more letter at a random position. Find the letter that was added in …

Mybatis源码之数据源模块分析

先来看看java纯jdbc查询数据的示例&#xff1a; try {//加载对应的驱动类Class.forName("com.mysql.cj.jdbc.Driver");//创建连接Connection connection DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test?serverTimezoneUTC", "roo…

Mybatis源码之缓存模块分析

缓存这个东西在很多应用中都能看到它们的身影&#xff0c;这次就讲讲在Mybatis中的缓存是怎么应用的&#xff0c;虽然说吧Mybatis中的缓存基本不怎么用&#xff0c;用的更多是第三方组件redis、MongoDB、MemCache等等。 Mybatis的缓存是基于Map实现的&#xff0c;从缓存中读写…

Mybatis源码之核心流程分析

终于谈到了Mybatis最核心的东西了&#xff0c;最核心的就是通过配置XML文件或注解中的SQL&#xff0c;直接调用接口就能执行配置好的SQL语句并封装成对应的返回类型的数据。 先看一下Mybatis使用示例&#xff1a; //创建Builder对象 SqlSessionFactoryBuilder builder new S…

Mybatis源码之与Spring集成包

这次讲讲Mybatis与Spring的整合&#xff0c;作为两款优秀的开源框架&#xff0c;被大众广泛使用&#xff0c;自然是需要强强联合的。 使用示例 先看一下怎么使用&#xff0c;首先需要引用这两款框架的jar包&#xff1a; <dependency>//spring-webmvc会自动去引入其他S…

Mybatis源码之插件模块分析

总结完这个Mybatis的整体主要功能基本上就差不多完&#xff0c;还有一些细节的部分&#xff0c;后续都会记录补充。 插件这个东西一般用的比较少&#xff0c;就算用的多的插件也算是PageHelper分页插件&#xff1b; PageHelper官网&#xff1a;https://github.com/pagehelper…

AMD推出7nm高端显卡Radeon VII,直指英伟达RTX 2080

显卡战争已经发展到了2019年&#xff0c;并且变得比任何人预想的都要激烈。 CES 2019大会上&#xff0c;AMD发布了第一款消费级的 7nm GPU&#xff0c;取名&#xff1a;Radeon VII。据了解&#xff0c;这不是 AMD 的第一颗 7nm 处理器&#xff08;早期以 AI 运算为主的 Radeon …

Spring集成Mybatis多数据源配置

既然在整理Mybatis那就把经常用的这个多数据源的笔记也整一下吧。 Spring集成Mybatis在之前就已经提到了。Spring集成Mybatis 集成Mybatis多数据源有两种方式&#xff1a; 1、创建多个SqlSessionFactory&#xff0c;扫描每个SqlSessionFactoryBean对应的包&#xff0c;形成了…

Spring文件上传

2019独角兽企业重金招聘Python工程师标准>>> Spring文件上传 1、所需依赖包&#xff1a;commons-fileupload-1.3.1.jar2、Maven配置文件pom.xml文件中加入依赖Jar包<dependency><groupId>commons-fileupload</groupId><artifactId>commons-…

算法题学到的一些小语言细节

1.要学会用i&#xff1b;可以简化很多代码&#xff1a;i&#xff1b;copyFromMe(i)&#xff1b;可以写成&#xff1a;copyFromeMe(i) 2.StringBuffer也跟列表一样有append函数&#xff1b; 3.if语句是分支不能进行循环&#xff0c;要写成while才能替代循环里面的判断 4. 这里的…

Zookeeper基础常用操作以及ACL权限

这次将Zookeeper的一些基础用法以及权限这块的都补充一下在这篇博客中。 上篇博客介绍了基于ZooKeeper实现的分布式锁&#xff0c;也介绍了一些ZooKeeper的节点类型以及监听机制&#xff0c;今天这里就不作过多的介绍了&#xff0c;大家也可以自行的去官方文档上看看更具体的介…

[中医经络学习一]足阳明胃经

人体有六脏&#xff08;心、肝、脾、肺、肾五脏&#xff0c;再加心包&#xff09;六腑&#xff08;胃、小肠、大肠、膀胱、胆、三焦&#xff09;&#xff0c;每个脏腑都联接着一条经络&#xff0c;一共12条经络&#xff0c;称“十二正经”&#xff0c;经络的走向在四肢两侧基本…

ThreadLocal原理解析以及是否需要调用remove方法

平常的开发过程中&#xff0c;如果有个类不是线程安全的&#xff0c;比如SimpleDateFormat&#xff0c;要使这个类在并发的过程中是线程安全的&#xff0c;那么可以将变量设置位局部变量&#xff0c;不过存在的问题就是频繁的创建对象&#xff0c;对性能和资源会有一定降低和消…

Maven基础及概念

前言 今天就来聊聊Maven的基础和一些比较概念性的东西&#xff0c;还有一些常用的Maven命令啥的&#xff0c;主要是某人脑子记不住&#xff0c;记在博客中让她自己看吧&#xff0c;省的费心给她找。 后续的文章会聊到Maven的一些比较高级用法&#xff0c;像自定义插件&#x…

Maven之pom.xml常用标签解析及镜像配置

前言 Maven仅仅是个打包工具而已&#xff0c;个人觉得没有太大必要花费在打包工具上&#xff0c;这里就列举一下个人觉得会常用标签的使用就好了&#xff0c;原理啥的基本就不太会去深度了解了&#xff0c;如果以后遇到需了解Maven工作原理的工作的话&#xff0c;到时候一定分…

Maven高级之插件开发

前言 终于来到了Maven的插件开发&#xff0c;其实Maven的插件并没有想象的那么难&#xff0c;刚开始讲Maven基础的时候就演示了一下JDK是如何打包的&#xff0c;Maven打包只是在JDK打包上封装了一层而已&#xff0c;Maven也支持自定义插件开发 创建 我们先使用quickstart原型…

Maven高级之archetype(原型/骨架)开发

前言 archetype这个的主要功能就是将写好的项目模块打包成一个原型&#xff0c;然后提供给其他人使用&#xff0c;这样别人就可以快速使用这个项目模板了。 这个东西虽然很多人都基本用不上&#xff0c;但原型这个东西用的好还是很方便的&#xff0c;能够在开发新项目上省去大…

深度学习在搜索业务中的探索与实践

本文根据美团高级技术专家翟艺涛在2018 QCon全球软件开发大会上的演讲内容整理而成&#xff0c;内容有修改。引言 2018年12月31日&#xff0c;美团酒店单日入住间夜突破200万&#xff0c;再次创下行业的新纪录&#xff0c;而酒店搜索在其中起到了非常重要的作用。本文会首先介绍…