• MongoDB基础之查询文档操作


    1 查询操作

    1.1 定义

    MongoDB 查询文档使用 find() 方法
    find() 方法以非结构化的方式来显示所有文档。

    MongoDB 查询数据的语法格式如下:

    db.collection.find(query, projection)
    
    • 1

    相关参数:

    • query :可选,使用查询操作符指定查询条件
    • projection :可选,使用投影操作符指定返回的键。查询时返回文档中所有键值, 只需省略该参数即可(默认省略)
      若不指定 projection,则默认返回所有键,指定 projection 格式如下(0:不显示,1:显示),有两种模式,但是两种模式不可混用
      • db.collection.find(query, {title: 1, by: 1}) inclusion模式 指定返回的键,不返回其他键
      • db.collection.find(query, {title: 0, by: 0}) exclusion模式 指定不返回的键,返回其他键
        比如:_id 键默认返回,需要主动指定 _id:0 才会隐藏

    1.2 查询操作

    1.2.1 基础查询

    1.2.1.1 pretty

    如果需要以易读的方式来读取数据,可以使用 pretty() 方法,语法格式如下:

    >db.col.find().pretty()
    
    • 1

    pretty() 方法以格式化的方式来显示所有文档。

    除了 find() 方法之外,还有一个 findOne() 方法,它只返回一个文档。

    1.2.1.2 求总数

    count()函数主要求总数

    求集合中总数
    db.col.count();
    求过滤后的总数
    db.col.find().count();
    
    • 1
    • 2
    • 3
    • 4

    注意
    在和分页联合使用时需要注意:

    count()函数是假即:0或空,则查询出来是总数量
    db.goods.find().count(); // 31
    db.goods.find().skip(2).limit(3).count();  //31
    db.goods.find().skip(2).limit(3).count(0);  //31
    
    count(1)函数是假即:1,则查询出来是实际数量
    db.goods.find().skip(2).limit(3).count(1);  //3
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    1.2.2 查询表达式

    MongoDB查询表达式说明

    查询表达式对应SQL表达式示例说明描述备注
    $gt>{field:{$gt:value}}查询大于某条件的值
    $gte>={field:{$gte:value}}查询大于或等于某条件的值
    $lt<{field:{$lt:value}}查询小于某条件的值
    $lte<={field:{$lte:value}}查询小于或等于某条件的值
    $eq={field:{$eq:value}}查filed列的值 等于 value 的文档也可以直接用冒号:表示等于
    $ne!={field:{$ne:value}}查filed列的值 不等于 value 的文档
    $inindb.book.find({like:{$in:[10,11,20]}});查询在集合中的值
    $ninnot indb.book.find({like:{$nin:[10,11,20]}});查询不在集合中
    $all无对应项,指数组所有单元匹配{field:{$all:[v1,v2..]}} 取出 field列是一个数组,且至少包含 v1,v2值
    $slice无对应项,限制数组元素的个数$slice:[a,b]a是正数时,起始位置是a+1,a是负数时,起始位置a(倒数数组),b是输出个数
    $oror{$or:[{filed1:value1,filed2:value2}]}查询出满足fileld1或者field2条件的文档
    $andand{$and:[{filed1:value1,filed2:value2}]}查询出既有field1又有field2字段的文档还可以用逗号表示and,每个键(key)以逗号隔开,即常规 SQL 的 AND 条件
    $notnotdb.book.find({like:{$not:{$in:[10]}}});not可以和其他连用这里是和in连用,表示不在集合中的文档
    $nor无对应项,指所有列举条件都不应成功为真{$nor:[条件1,条件2]}所有条件都不满足的文档为真返回
    $exists无对应项,某列存在则为真{field:{$exists:1}}查询出含有field字段的文档
    $mod无对应项,满足某求余则为真db.book.find({field:{$mod:[3,2]}});查询出含有field字段除数为3余数为2的文档,即:field%3==2
    $type无对应项,满足某类型则为真{field:{$exists:1}}查询出含有field字段的文档
    $wherewheredb.goods.find({$where:'this.cat_id != 3 && this.cat_id != 11'});可以写成类似于SQL的语法$where查询时, mongodb是把bson结构的二进制数据转换为json结构的对象,然后比较对象的属性是否满足表达式.速度较慢
    $regex正则表达式匹配则为真db.posts.find({tags:{$regex:"jav"}})正则表达式效率和$where一样也不是很高

    $type操作符是基于BSON类型来检索集合中匹配的数据类型,并返回结果。
    MongoDB中可以使用的类型如下表所示:

    类型数字备注
    Double1
    String2
    Object3
    Array4
    Binary data5
    Undefined6已废弃。
    Object id7
    Boolean8
    Date9
    Null10
    Regular Expression11
    JavaScript13
    Symbol14
    JavaScript (with scope)15
    32-bit integer16
    Timestamp17
    64-bit integer18
    Min key255Query with -1.
    Max key127

    如果想获取 合中 为 String 的数据,可以使用以下命令:

    db.col.find({"title" : {$type : 2}})'string'必须以字符串形式
    db.col.find({"title" : {$type : 'string'}})
    
    • 1
    • 2
    • 3

    1.2.3 分页排序

    1.2.3.1 分页limit

    如果需要在MongoDB中读取指定数量的数据记录,可以使用MongoDBLimit方法,limit()方法接受一个数字参数,该参数指定从MongoDB中读取的记录条数。

    limit()方法基本语法如下所示:

    >db.COLLECTION_NAME.find().limit(NUMBER)
    
    • 1

    注意:如果没有指定limit()方法中的参数则显示集合中的所有数据。

    1.2.3.2 分页skip

    我们除了可以使用limit()方法来读取指定数量的数据外,还可以使用skip()方法来跳过指定数量的数据,skip方法同样接受一个数字参数作为跳过的记录条数。

    skip() 方法脚本语法格式如下:

    >db.COLLECTION_NAME.find().limit(NUMBER).skip(NUMBER)
    
    • 1

    以下实例只会显示第二条文档数据

    >db.col.find({},{"title":1,_id:0}).limit(1).skip(1)
    { "title" : "Java 教程" }
    
    • 1
    • 2

    注意skip()方法默认参数为 0 。

    limit(n).skip(n)连用相当于关系型数据库中的分页操作
    limit(n) 是用来规定显示的条数,而skip(n) 是用来在符合条件的记录中从第一个记录跳过的条数,这两个函数可以交换使用。
    比如:find({},{age:1,_id:0}).limit(2).skip(1),在符合条件的文档中,要显示两条文档,显示的位置从跳过第一条记录开始

    但是skiplimit方法只适合小数据量分页,如果是百万级效率就会非常低,因为skip方法是一条条数据数过去的,建议使用where_limit过滤处理
    这里我们假设查询第100001条数据,这条数据的Amount值是:2399927,我们来写两条语句分别如下:

    b.test.sort({"amount":1}).skip(100000).limit(10)  耗时183ms
    db.test.find({amount:{$gt:2399927}}).sort({"amount":1}).limit(10)  耗时53ms
    
    • 1
    • 2
    1.2.3.3 排序sort

    MongoDB 中使用 sort() 方法对数据进行排序,sort() 方法可以通过参数指定排序的字段,并使用 1-1 来指定排序的方式

    • 1 升序排列
    • -1是用于降序排列

    sort()方法基本语法如下所示:

    >db.COLLECTION_NAME.find().sort({KEY:1})
    
    • 1

    注意:当skip(), limilt(), sort()三个放在一起执行的时候,执行的顺序是先 sort(), 然后是 skip(),最后是显示的limit()

    1.2.4 正则表达式

    MongoDB 使用 $regex 操作符来设置匹配字符串的正则表达式。
    MongoDB使用PCRE (Perl Compatible Regular Expression) 作为正则表达式语言

    我们使用正则表达式不需要做任何配置。

    准备文档,该文档包含了文章内容和标签:

    {
       "post_text": "enjoy the mongodb articles on java",
       "tags": [
          "mongodb",
          "java"
       ]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    1.2.4.1 使用正则表达式

    以下命令使用正则表达式查找包含 java字符串的文章:

    db.posts.find({post_text:{$regex:"java"}})
    
    • 1

    以上查询也可以写为/ /,这是JavaScript中正则写法:

    db.posts.find({post_text:/java/})
    
    • 1
    1.2.4.2 不区分大小写的正则表达式

    如果检索需要不区分大小写,我们可以设置 $options$i
    以下命令将查找不区分大小写的字符串 java:

    >db.posts.find({post_text:{$regex:"java",$options:"$i"}})
    
    • 1

    集合中会返回所有包含字符串 java的数据,且不区分大小写:

    {
       "_id" : ObjectId("53493d37d852429c10000004"),
       "post_text" : "hey! this is my post on  java", 
       "tags" : [ "java" ]
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    1.2.4.3 数组元素使用正则表达式

    还可以在数组字段中使用正则表达式来查找内容。 这在标签的实现上非常有用,如果需要查找包含以 ja 开头的标签数据(va 或 jav或 java), 可以使用以下代码:

    db.posts.find({tags:{$regex:"jav"}})
    
    • 1
    1.2.4.4 优化正则表达式查询

    如果文档中字段设置了索引,那么使用索引相比于正则表达式匹配查找所有的数据查询速度更快。
    如果正则表达式是前缀表达式,所有匹配的数据将以指定的前缀字符串为开始。例如: 如果正则表达式为 ^tut ,查询语句将查找以 tut 为开头的字符串。
    这里面使用正则表达式需要注意:
    正则表达式中使用变量。一定要使用eval将组合的字符串进行转换,不能直接将字符串拼接后传入给表达式。否则没有报错信息,只是结果为空!实例如下:

    var name=eval("/" + 变量值key +"/i"); 
    
    • 1

    以下是模糊查询包含title关键词, 且不区分大小写:

    title:eval("/"+title+"/i")    
    等同于 title:{$regex:title,$Option:"$i"}   
    
    • 1
    • 2

    1.3 游标

    1.3.1 定义

    通俗的说,游标不是查询结果,而是查询的返回资源,或者接口,通过这个接口,可以逐条读取

    1.3.2 游标声明

    var cursor =  db.collectioName.find(query,projection);
    cursor.hasNext(); 判断游标是否已经取到尽头
    cursor. Next(); 取出游标的下1个单元
    
    • 1
    • 2
    • 3

    用while来循环游标

    > var mycursor = db.bar.find({_id:{$lte:5}})
    > while(mycursor.hasNext()) {
    ... printjson(mycursor.next());
    ... }
    
    • 1
    • 2
    • 3
    • 4

    用for循环

    // 声明游标
    var cursor = db.goods.find();
    // 循环游标
    for(var doc=true;cursor.hasNext();) { printjson(cursor.next());}
    
    也可以简写:
    for(var  cursor=db.goods.find(), doc=true;cursor.hasNext();) { printjson(cursor.next());}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    1.3.3 操作游标

    游标还有一个迭代函数,允许我们自定义回调函数来逐个处理每个单元.
    cursor.forEach(回调函数);

    var gettitle = function(obj) {print(obj.goods_name)}
    var cursor = db.goods.find();
    cursor.forEach(gettitle);
    
    • 1
    • 2
    • 3

    通过cursor一次性得到所有数据, 并返回数组.

    var cursor = db.goods.find();
    printjson(cursor.toArray());  //看到所有行
    printjson(cursor.toArray()[2]);  //看到第2行
    
    • 1
    • 2
    • 3

    注意:不要随意使用toArray(),原因: 会把所有的行立即以对象形式组织在内存里.可以在取出少数几行时,用此功能

  • 相关阅读:
    Streamlit 构建大语言模型 (LLM) web 界面
    Java程序员常用的Eclipse键盘快捷键,建议收藏
    物联网的应用——工业自动化
    基于SpringBoot的体育场运营系统
    二分查找详解
    1.6 IntelliJ IDEA开发工具
    Ubuntu-22.04安装MegaCLI并查看MegaRAID的配置
    table的宽高适配方法
    linux系统编程3—文件存储函数
    BEVFusion:A Simple and Robust LiDAR-Camera Fusion Framework 论文笔记
  • 原文地址:https://blog.csdn.net/u012060033/article/details/127692381