十一:文档 Document 查询非典型篇

一灰灰BlogDBMongoMongoDB约 742 字大约 2 分钟

前面介绍的查询可以说是常见的典型case,但是mongodb中有两个比价特殊的数据类型,数组 + 对象,自然的也会有一些非典型的查询case,下面主要针对这两种数据类型的查询姿势,给出实例讲解

1. 数组

首先准备一些供数组操作的文档如下

{ "_id" : ObjectId("5e7b5ac10172dc950171c488"), "name" : "一灰灰blog", "age" : 19, "skill" : [ "java", "python", "sql" ], "tag" : 2 }
{ "_id" : ObjectId("5e7b5ac40172dc950171c489"), "name" : "一灰灰blog", "age" : 20, "skill" : [ "web", "shell", "js" ], "tag" : 1 }
{ "_id" : ObjectId("5e7b5bb085a742842d2e23fc"), "name" : "一灰灰", "age" : 18, "sex" : "man", "tag" : 2 }
{ "_id" : ObjectId("5e7b5c2e0172dc950171c48a"), "name" : "一灰灰", "age" : 18, "hobby" : [ "play game" ] }
{ "_id" : ObjectId("5e7c5627f020f58f5323e52d"), "name" : "一灰灰2", "age" : 22, "skill" : [ "android", "ios" ] }

长度查询

根据数组长度进行查询,借助$size来统计数组长度

# 查询数组长度为3的文档
db.doc_demo.find({'skill': {$size: 3}})

长度范围查询

请注意,不支持长度的比较查询,如下,会报语法错误

db.doc_demo.find({'skill:{$size: {$gt: 2}}})

要实现范围查询,可以借助$where来实现($where比较强大,后面单独说明)

# 请注意判空需要有
db.doc_demo.find({$where:'this.skill !=null && this.skill.length>2'})

数组内容查询

根据数组内容进行查询,常见的有两种方式,一个是直接根据数组定位比较如

# 查询skill数组中,第一个元素为java的文档
db.doc_demo.find({'skill.0': 'java'})

上面这种实用性可能并不大,另外一个常见的case就是查询数组中包含某个元素的文档,这时可以借助$elemMatch来实现

# 查询skill数组中包含 java 元素的文档
db.doc_demo.find({'skill': {$elemMatch: {$eq: 'java'}}})

说明,当数组的元素是Object类型时,还可以用右边这种姿势:db.doc_demo.find({'skill': {$elemMatch: {'subField': 'xxx'}}})

2. Object

因为mongodb支持内嵌文档,所以根据内嵌文档进行查询的场景也是不少的

首先准备三个用于后续查询测试的文档

{ "_id" : ObjectId("5e7c5a61f020f58f5323e52e"), "name" : "一灰灰", "doc" : { "title" : "简单的标题", "content" : "简单的内容", "tag" : [ "java", "后端" ] } }
{ "_id" : ObjectId("5e7c5a8af020f58f5323e52f"), "name" : "一灰灰", "doc" : { "title" : "哈哈", "content" : "嘻嘻哈哈", "tag" : [ "随笔" ], "draft" : true } }
{ "_id" : ObjectId("5e7c5ae7f020f58f5323e530"), "name" : "一灰灰", "doc" : { "title" : "22", "content" : "3333", "tag" : [ "随笔" ], "draft" : false, "visit" : 10 } }

根据内嵌文档字段查询

查询姿势和field查询相似,只是需要注意一下key的语法为: field.subField, 实例如下

db.doc_demo.find({'doc.title': '22'})

存在性查询

查询嵌入文档包含某个field的case,和普通的查询姿势也一样

db.doc_demo.find({'doc.visit': {$exists: true}})

排序

根据Object的成员进行排序,操作姿势也基本一样

db.doc_demo.find({'doc': {$exists: true}}).sort({'doc.visit': -1})
Loading...