MongoDB学习 (五):查询操作符(Query Operators).1st

本文地址:http://www.cnblogs.com/egger/archive/2013/05/04/3059374.html欢迎转载 ,请保留此链接๑•́ ₃•̀๑!

查询操作符(Query Operators)可以让我们写出复杂查询条件,让我们使用的过程更加灵活。

官方文档中使用的“field”单词,RDBMS中是字段的意思,但是MongoDB作为文档数据库,使用的BSON格式作为数据存储格式。field对应key,我这里还是把他翻译成“字段”而不是“键”。若有不妥,请指出。

演示数据:

我们将实际操作下。先向集合inventory插入3条数据,文档内容如下:

{"name":"t1","amount":16,"tags":[ "school", "book", "bag", "headphone", "appliances" ]}

{"name":"t2","amount":50,"tags":[ "appliances", "school", "book" ]}

{"name":"t3","amount":58,"tags":[ "bag", "school", "book" ]}

比较查询操作符 Comparison Query Operators

$all

语法: { field: { $all: [ , ... ] }

field:文档中键的名称(不使用双引号)。

匹配那些指定键的键值中包含数组,而且该数组包含条件指定数组的所有元素的文档。

db.inventory.find( { tags: { $all: [ "appliances", "school", "book" ] } } )

查询出在集合inventory中tags键值包含数组,且该数组中包含appliances、school、book元素的所有文档  ,因此该查询将匹配tags键值包含如下任意数组的所有文档。

[ "school", "book", "bag", "headphone", "appliances"]

["appliances", "school", "book" ]

执行上面的查询语句,

文档中键值类型不是数组,也可以使用$all操作符进行查询操作,如下例所示:

//查询结果是相同的,匹配amount键值等于50的文档db.inventory.find( { amount: {$all:[50]}} )

db.inventory.find( { amount:50}} )

$gt

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

匹配键值大于指定值的所有文档。

$gte

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

匹配键值不小于指定值的所有文档。

$lt

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

匹配键值小于指定值的所有文档。

$lte

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

匹配键值不大于指定值的所有文档。

//下面将查询amount键值大于50的文档:db.inventory.find( { amount: { $gt: 50} } )//下面将查询amount键值不小于(大于等于)50的文档:db.inventory.find( { amount: { $gte: 50} } )//下面将查询amount键值小于50的文档:db.inventory.find( { amount: { $lt: 50} } )//下面将查询amount键值不大于(小于等于)50的文档:db.inventory.find( { amount: { $lte: 50 } } )

$in

语法: { field: { $in: [, , ... ] } }

匹配键值等于指定数组中任意值的文档。类似sql中in.

$nin

语法: { field: { $nin: [ , ... ]} }

匹配键不存在或者键值不等于指定数组的任意值的文档。

查询出amount键值为16或者50的文档:

db.inventory.find( { amount: { $in: [ 16, 50 ] } } )

//查询出amount键值不为16或者50的文档db.inventory.find( { amount: { $nin: [ 16, 50] } } )//查询出qty键值不为16或50的文档,由于文档中都不存在键qty,所以返回所有文档db.inventory.find( { qty: { $nin: [ 16, 50 ] } } )

$ne

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

匹配键值不等于指定值的文档。

查询出amount键值不等于58的文档:

db.inventory.find( { amount: { $ne: 58} } )//$nin查询结果相同db.inventory.find( { amount: { $nin: [58] } } )

逻辑查询操作符 Logical Query Operators

$and

语法: { $and: [ { }, { } , ... , { } ] }

and指定一个至少包含两个表达式的数组,选择出满足该数组中所有表达式的文档。and指定一个至少包含两个表达式的数组,选择出满足该数组中所有表达式的文档。and操作符使用短路操作,若第一个表达式的值为“false”,余下的表达式将不会执行。

//选择name为“t1”,amount值小于50的文档数据db.inventory.find({ $and: [ { name: "t1" }, { amount: { $lt:50 } } ] } )

对于下面使用逗号分隔符的表达式列表,MongoDB会提供一个隐式的$and操作:

//等同于{ $and: [ { name: "t1" }, { amount: { $lt:50 } } ] }db.inventory.find({ name: "t1" , amount: { $lt:50 }} )

$nor

语法: { $nor: [ { }, { }, ... { } ] }

$nor执行逻辑NOR运算,指定一个至少包含两个表达式的数组,选择出都不满足该数组中所有表达式的文档。

//选择name不为“t1”,amount值不小于50的文档数据db.inventory.find( { $nor: [ { name: "t1" }, { qty: { $lt: 50 } } ] } )

//若是文档中不存在表达式中指定的键,表达式值为false; false nor false 等于 true,所以选择集合所有文档db.inventory.find( { $nor: [ { sale:true}, { qty: { $lt: 50 } } ] } )

$not

语法: { field: { $not: { } } }

$not执行逻辑NOT运算,选择出不能匹配表达式的文档 ,包括没有指定键的文档。

$not操作符不能独立使用,必须跟其他操作一起使用(除$regex)。

//选择amount值不大于50的文档数据db.inventory.find( { amount: { $not: { $gt: 50 } } } )

//指定的键gty,文档中都不存在无法匹配表示,所以返回集合所有文档数据。db.inventory.find( { gty: { $not: { $gt: 50 } } } )

$or

语法: { $or: [ { }, { }, ... , { } ] }

$or执行逻辑OR运算,指定一个至少包含两个表达式的数组,选择出至少满足数组中一条表达式的文档。

//选择amount的键值大于50或者name的键值为t1的文档db.inventory.find( { $or: [ { amount: { $gt: 50 } }, { name: "t1" } ] } )

元素查询操作符 Element Query Operators

$exists

语法: { field: { $exists: } }

如果$exists的值为true,选择存在该字段的文档;若值为false则选择不包含该字段的文档。

//查询不存在qty字段的文档(所有文档)db.inventory.find( { qty: { $exists:false} })//查询amount字段存在,且值不等于16和58的文档db.inventory.find( { amount: { $exists:true, $nin: [ 16, 58 ] } } )

如果该字段的值为null,$exists的值为true会返回该条文档,false则不返回。

//向集合中插入一条amount键值为null的文档{"name":"t4","amount":null,"tags":[ "bag", "school", "book"]}//0条数据db.inventory.find( { amount: { $exists:false} } )//所有的数据db.inventory.find( { amount: { $exists:true} } )

$mod

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

匹配字段值对(divisor)取模,值等于(remainder)的文档。

//选择集合中 amount 字段的值为 4 的 0 次模数的所有文档,例如 amount 值等于 16 的文档db.inventory.find( { amount: { $mod: [ 4, 0 ] } } )

有些情况下,我们可以使用mod操作符替代使用求模表达式的mod操作符替代使用求模表达式的where操作符,因为后者代价昂贵。

db.inventory.find( { $where: "this.amount % 4 == 0" } )

注意:返回结果怎么不一样。因为有一条文档的amount键值为null,javascript中null进行数值转换,会返回。所以该条文档匹配where操作符求模式了表达式。当文档中字段值不存在null,就可以使用where操作符求模式了表达式。当文档中字段值不存在null,就可以使用mod替代$where的表达式.

$type

语法: { field: { $type: } }

选择字段值为指定的BSON数据类型的文档.使用下面类型对应的编号:

类型类型编号

Double双精度1

String字符串2

Object对象3

Array数组4

Binary data二进制对象5

Object id对象id7

Boolean布尔值8

Date日期9

Null未定义10

Regular Expression正则表达式11

JavaScriptJavaScript代码13

Symbol符号14

JavaScript (with scope)JavaScript代码(带范围)15

32-bit integer32 位整数16

Timestamp时间戳17

64-bit integer64 位整数18

Min key最小键255

Max key最大键127

如果文档的键值是一个数组。那么$type将对数组里面的元素进行类型匹配而不是键值数组本身。

db.inventory.find( { tags: { $type : 4} } )//如果想检查键值的类型是否为数组类型,使用$where操作符db.inventory.find( { $where : "Array.isArray(this.tags)" } )

下面例子展示了文档中类型(包括MinKey 和MaxKey):

db.type.insert( {x : 3});

db.type.insert( {x :2.9} );

db.type.insert( {x :newDate()} );

db.type.insert( {x :true} );

db.type.insert( {x : MaxKey } )

db.type.insert( {x : MinKey } )>db.type.find()

{"_id" : ObjectId("5185f9cfa1adf7d5f458505e"), "x" : 3}

{"_id" : ObjectId("5185f9cfa1adf7d5f458505f"), "x" : 2.9}

{"_id" : ObjectId("5185f9cfa1adf7d5f4585060"), "x" : ISODate("2013-05-05T06:18:

55.751Z") }

{"_id" : ObjectId("5185f9cfa1adf7d5f4585061"), "x" :true}

{"_id" : ObjectId("5185f9cfa1adf7d5f4585062"), "x" : { "$maxKey" : 1} }

{"_id" : ObjectId("5185f9d0a1adf7d5f4585063"), "x" : { "$minKey" : 1 } }

要查询的字段值为MinKey,使用下面的语法:

db.collection_name.find( { field: { $type: -1 } } )

JavaScript查询操作符  JavaScript Query Operators

$regex

regex操作符查询中可以对字符串的执行正则匹配。MongoDB使用Perl兼容的正则表达式(PCRE)库来匹配正则表达式.可以使用正则表达式对象或者regex操作符查询中可以对字符串的执行正则匹配。MongoDB使用Perl兼容的正则表达式(PCRE)库来匹配正则表达式.可以使用正则表达式对象或者regex操作符.

//查询name键值以“4”结尾的文档db.inventory.find( { name: /.4/i } );

db.inventory.find( { name: { $regex:'.4', $options: 'i' } } );

options(options(regex 提供四个选项标志)

i   如果设置了这个修饰符,模式中的字母会进行大小写不敏感匹配。

m   默认情况下,PCRE 认为目标字符串是由单行字符组成的(然而实际上它可能会包含多行).如果目标字符串 中没有 "\n"字符,或者模式中没有出现“行首”/“行末”字符,设置这个修饰符不产生任何影响。

s    如果设置了这个修饰符,模式中的点号元字符匹配所有字符,包含换行符。如果没有这个修饰符,点号不匹配换行符。

x    如果设置了这个修饰符,模式中的没有经过转义的或不在字符类中的空白数据字符总会被忽略,并且位于一个未转义的字符类外部的#字符和下一个换行符之间的字符也被忽略。 这个修饰符使被编译模式中可以包含注释。 注意:这仅用于数据字符。 空白字符 还是不能在模式的特殊字符序列中出现,比如序列 。

注:JavaScript只提供了i和m选项,x和s选项必须使用$regex操作符。

$where

$where操作符功能强大而且灵活,他可以使用任意的JavaScript作为查询的一部分,包含JavaScript表达式的字符串或者JavaScript函数。

最典型的应用就是比较文档中的两个键的值是否相等.

//插入两条数据db.fruit.insert({"apple":1, "banana": 4, "peach" : 4})

db.fruit.insert({"apple":3, "banana": 3, "peach" : 4})

查找出banana等于peach键值的文档(4种方法):

//字符串形式db.fruit.find( { $where: "this.banana == this.peach"} )

db.fruit.find( { $where:"obj.banana == obj.peach"} )//函数形式db.fruit.find( { $where:function() {return(this.banana ==this.peach) } } )

db.fruit.find( { $where:function() {returnobj.banana == obj.peach; } } )

查出文档中存在的两个键的值相同的文档。

>db.fruit.find({$where:function() {for(varcurrentinthis) {for(varotherinthis) {if(current != other &&this[current] ==this[other]) {returntrue;

}

}

}returnfalse;

}});

不是非常必要时,一定要避免使用"Where"査询,因为它们在速度上要比常规査询慢很多。每个文档都要从BSON转换成JavaScript对象,然后通过"Where"査询,因为它们在速度上要比常规査询慢很多。每个文档都要从BSON转换成JavaScript对象,然后通过"where"的表达式来运行。同样还不能利用索引。所以,只在走投无路时才考虑"$where"这种用法。

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

推荐阅读更多精彩内容