• Mongodb 使用需要避免的"坑"


    前提

    mongodb版本是 4.4.14

    root@8163d7b355e7:/# mongo --version
    MongoDB shell version v4.4.14
    Build Info: {
        "version": "4.4.14",
        "gitVersion": "0b0843af97c3ec9d2c0995152d96d2aad725aab7",
        "openSSLVersion": "OpenSSL 1.1.1f  31 Mar 2020",
        "modules": [],
        "allocator": "tcmalloc",
        "environment": {
            "distmod": "ubuntu2004",
            "distarch": "x86_64",
            "target_arch": "x86_64"
        }
    }
    root@8163d7b355e7:/# 
    

    建立一张demo表并,初始化两条int32类型的数据

    db.demo.insert({"params1" : NumberInt(1),"params2" : NumberInt(1)})
    

    如下

    mongodb bson类型查询表

    bson 每个数据类型都有一个相应的数字和字符串别名,可以与$ type运算符一起使用BSON类型查询文档。

    Type Number Alias Notes
    Double 1 double
    String 2 string
    Object 3 object
    Array 4 array
    Binary data 5 binData
    Undefined 6 undefined
    ObjectId 7 objectId
    Boolean 8 bool
    Date 9 date
    Null 10 null
    Regular Expression 11 regex
    DBPointer 12 dbPointer
    JavaScript 13 javascript
    Symbol 14 symbol
    JavaScript (with scope) 15 javascriptWithScope
    32-bit integer 16 int
    Timestamp 17 timestamp
    64-bit integer 18 long
    Min key -1 minKey
    Max key 127 maxKey

    mongo shell 更改类型的问题

    开始时初始化数据生成了一条数据,分别为 params1(1) int32, params2(2) int32

    现在如果想把params1的数据改为int64一般使用的做法是,通过mongodb客户端,执行以下命令

    根据bson类型查询表找到int32类型的数据,循环更新为int64

    db.demo.find({"params1" : {$type : 16}}).forEach(function(x) {
    	x.params1 = NumberLong(x.params1);
    	db.demo.save(x);
    })
    

    执行结果如下

    params1 的类型被改成了Int64,但是并没有更改params2的数据,params2却从Int32变成了Double类型。

    分析如下

    导致该情况出现的原因是因为mongo shell 是js实现的,而js不是一个类型化语言。

    通过查询mongodb官方文档
    https://www.mongodb.com/docs/manual/core/shell-types/?_ga=2.43697382.294185521.1652615680-1710587817.1652615680

    得到如下解释

    The mongo shell treats all numbers as 64-bit floating-point double values by default.
    

    意思是默认情况下,mongo shell 将所有数字视为int64 和 double类型,也就是说,通过mongo shell更改类型 除了int64 和 double类型的数字数据都会自动转换成double类型。

    解决方案

    更改类型建议使用后端驱动程序进行更改,而不是通过mongo shell。

    $where 自查询无法比较int64和int64类型的数据

    当前数据库有一条数据,params1 和 params2

    执行语句

    db.demo.find({"$where" : "this.params1 == this.params2"})
    

    返回结果如下

    • params1类型int32,params2类型int32 返回有值
    • params1类型int64,params2类型int32 返回有值
    • params1类型double,params2类型int32 返回有值
    • params1类型double,params2类型int64 返回有值
    • params1类型int64,params2类型int64 返回为空

    得出结论

    在$where 子查询中,只有int64和int64之间无法比较,其他类型之间可以相互比较,所以慎用$where子查询。

  • 相关阅读:
    DDD(Domain Driven Design) 架构设计
    兴哥:美团下一个十年,要让新一批管理者成长起来
    Java设计模式-Builder构造者模式
    社会需要转型变革,自己更需要转型变革-屡败屡战
    Guava 源码分析之Cache的实现原理
    缓存算法(FIFO 、LRU、LFU三种算法的区别)
    Guava---缓存之LRU算法
    Boost.Asio 网络编程([译]Boost.Asio基本原理)
    浅谈 Boost.Asio 的多线程模型
    boost.asio系列——io_service
  • 原文地址:https://www.cnblogs.com/smallbo/p/16274740.html
Copyright © 2020-2023  润新知