mongoDB常规操作-查询操作符

前言

最近看Mongo权威指南的时候,偶然间查了下mongo的官方文档,发现其实增加了很多新的API,打算系统性的过一遍。

比较操作符

$eq

没啥用
因为
db.collectionName.find({"field":{$eq:"value"}})
等于
db.collectionName.find({"field":"value"})

$gt

语法: {field: {$gt: value} }

$gte

语法: {field: {$gte: value} }

$lt

语法: {field: {$lt: value} }

$lte

语法: {field: {$lte: value} }

$in

语法: {field: {$in: [ <value1>, <value2> ... <valueN> ]} }
尽量少用$in,而是分解成一个一个的单一查询。尤其是在分片上,$in会让你的查询去每一个分片上查一次,如果实在要用的话,先在每个分片上建索引。

$ne

语法: {field: {$ne: value} }
$ne查询会扫描整个collection, 即使是文档上面没有该field也会被扫描。性能会比较差

$nin

语法: { field: { $nin: [ <value1>, <value2> ... <valueN> ]} }
匹配两种文档

  1. field字段中没有指定数组的值
  2. 没有fileld字段的

查询会全表扫描。

逻辑查询符

逻辑操作符都是元操作符,意味着他们可以放在其他任何操作符之上

$and

语法: { $and: [ { <expression1> }, { <expression2> } , ... , { <expressionN> } ] }

第一个expression应筛去尽可能多的条件

$not

语法: { field: { $not: { <operator-expression> } } }

  • $not 在大部分操作符上行为始终一致,但是在一些数据类型(比如数组)可能会产生不同的结果
  • $not 操作符不支持 $regex操作符,但是可以使用//替代;
  • $not通常不知道如何使用索引
  • $not操作符与其他逻辑操作符语法有些不太一样

$or

语法: { $or: [ { <expression1> }, { <expression2> }, ... , { <expressionN> } ] }

  • 第一个expression1应匹配尽量多的结果
  • 使用$or查询,每个expression可以优先选用其自己的索引(而非符合索引)
  • 除非所有的expression都对应相应的索引,不然$or没有办法使用索引
  • 因为$text查询必须使用索引,所以当同时使用$or和$text的时候,必须所有的expression都有索引,不然会抛出错误
  • 如果有可能,尽量用$in代替$or

$nor

语法: { $nor: [ { <expression1> }, { <expression2> }, ... { <expressionN> } ] }

  • 当使用$nor去查询时,不仅包括不符合这个表达式的,还包括不存在于这个表达式中field字段
  • 可以和$exists配合使用,例如:
db.inventory.find( { $nor: [ 
    { price: 1.99 }, { price: { $exists: false } }, 
    { sale: true }, { sale: { $exists: false } }
 ] } )

元素查询操作符

$exists

语法: { field: { $exists: <boolean> } }

当为true时,匹配包含该字段的文档,即使该字段的值为null

  • 据mongodb权威指南说,该操作符不会用到索引

$type

语法: { field: { $type: <BSON type> } }{ field: { $type: [ <BSON type1> , <BSON type2>, ... ] } }

估算查询操作符

$expr

语法: { $expr: { <expression> } }
3.6版新增的语法,允许在查询中使用aggregation expression

  • 可以使用它比较一个文档中的不同field的值,例如:db.monthlyBudget.find( { $expr: { $gt: [ "$spent" , "$budget" ] } } )
  • 可以使用条件语句,例如
db.supplies.find( {
    $expr: {
       $lt:[ {
          $cond: {
             if: { $gte: ["$qty", 100] },
             then: { $divide: ["$price", 2] },
             else: { $divide: ["$price", 4] }
           }
       },
       5 ] }
} )

$jsonSchema

语法: { $jsonSchema: { <expression> } }
3.6版本新增语法: 讲文档与给定的JSON Schema文档进行匹配
示例如下:

db.createCollection("students", {
   validator: {
      $jsonSchema: {
         bsonType: "object",
         required: [ "name", "year", "major", "gpa" ],
         properties: {
            name: {
               bsonType: "string",
               description: "must be a string and is required"
            },
            gender: {
               bsonType: "string",
               description: "must be a string and is not required"
            },
            year: {
               bsonType: "int",
               minimum: 2017,
               maximum: 3017,
               exclusiveMaximum: false,
               description: "must be an integer in [ 2017, 3017 ] and is required"
            },
            major: {
               enum: [ "Math", "English", "Computer Science", "History", null ],
               description: "can only be one of the enum values and is required"
            },
            gpa: {
               bsonType: [ "double" ],
               description: "must be a double and is required"
            }
         }
      }
   }
})

$mod

语法: { field: { $mod: [ divisor, remainder ] } }

  • 返回字段值%divisor === remainder的文档
  • 如果数组内元素不等于两个会报错

$regex

语法: { field: { $mod: [ divisor, remainder ] } }
可以使用以下的形式

{ <field>: { $regex: /pattern/, $options: '<options>' } }
{ <field>: { $regex: 'pattern', $options: '<options>' } }
{ <field>: { $regex: /pattern/<options> } }

$text

语法:

{
  $text:
    {
      $search: <string>,
      $language: <string>,
      $caseSensitive: <boolean>,
      $diacriticSensitive: <boolean>
    }
}

$text 只在有text索引的field上进行搜索

$where

语法: ``

  • 在3.6版本中增加了$expr,与$where相比,不需要执行javascript,所以会快很多,优先使用$expr
  • $where只能用于最顶层的文档查询,不能用于内线文档或者数组的查询
  • $where无法使用索引

示例:

db.foo.find( { $where: function() {
   return (hex_md5(this.name) == "9b53e667f30cd329dca1ec9e6a83e994")
} } );

地理空间查询操作符

暂时略过

数组查询操作符

$all

语法: { <field>: { $all: [ <value1> , <value2> ... ] } }

$all查询用于全部value的指定文档

$elemMatch

语法: { <field>: { $elemMatch: { <query1>, <query2>, ... } } }

使用多个表达式去匹配数组的每一项,返回匹配成功的文档

$size

语法: { <field>: { $size: length} }

匹配数组的长度,只能是固定值,不能是范围

位查询操作符

暂时略过

Projection操作符

$

语法:

db.collection.find( { <array>: <value> ... },
                    { "<array>.$": 1 } )
db.collection.find( { <array.field>: <value> ...},
                    { "<array>.$": 1 } )

返回的文档中的数组只会保留匹配到的数组的那一项

$elemMatch

示例:

db.schools.find( { zipcode: "63109" },
                 { students: { $elemMatch: { school: 102, age: { $gt: 10} } } } )

返回的文档中会去掉不匹配的数组项,但是数组中匹配的项以及文档的其他项还是会如期的返回

$meta

暂时略过

$slice

示例:

db.collection.find( { field: value }, { array: {$slice: count } } );

返回的数组中含有多少项
如果是正数,表示返回的数组的前几个元素
如果是负数,表示返回数组的最后几个元素

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343

推荐阅读更多精彩内容