• MongoDB学习笔记五—查询上


    数据准备

    { "goods_id" : 1, "goods_name" : "KD876", "createTime" : ISODate("2016-12-21T11:19:39.010Z") }
    { "goods_id" : "4", "goods_name" : "诺基亚N85原装充电器", "createTime" : ISODate("2016-09-11T00:00:00Z") }
    { "goods_id" : 3, "goods_name" : "诺基亚原装5800耳机", "createTime" : ISODate("2016-10-09T00:00:00Z") }
    { "goods_id" : 5, "goods_name" : "索爱原装M2卡读卡器", "createTime" : ISODate("2016-12-21T11:19:39.010Z") }
    { "goods_id" : 6, "goods_name" : "胜创KINGMAX内存卡", "createTime" : ISODate("2016-12-21T11:19:39.010Z") }
    { "goods_id" : 7, "goods_name" : "诺基亚N85", "createTime" : ISODate("2016-12-21T11:19:39.010Z") }
    { "goods_id" : 8, "goods_name" : "飞利浦9@9v", "createTime" : ISODate("2016-12-21T11:19:39.010Z") }
    { "goods_id" : 9, "goods_name" : "诺基亚E66", "createTime" : ISODate("2016-12-21T11:19:39.010Z") }
    { "goods_id" : "10", "goods_name" : "索爱C702c", "createTime" : ISODate("2016-12-21T11:19:39.010Z") }
    { "goods_id" : 11, "goods_name" : "索爱C702c", "createTime" : ISODate("2016-12-21T11:19:39.010Z") }
    { "goods_id" : 12, "goods_name" : "摩托罗拉A810", "createTime" : ISODate("2016-12-21T11:19:39.010Z") }
    { "goods_id" : 13, "goods_name" : "诺基亚5320", "createTime" : ISODate("2016-12-21T11:19:39.010Z") }
    { "goods_id" : 14, "goods_name" : "诺基亚5800XM", "createTime" : ISODate("2016-12-21T11:19:39.010Z") }
    { "goods_id" : "15", "goods_name" : "摩托罗拉A810", "createTime" : ISODate("2016-12-21T11:19:39.010Z") }
    { "goods_id" : 16, "goods_name" : "恒基伟业G101", "createTime" : ISODate("2016-12-21T11:19:39.010Z") }
    { "goods_id" : 17, "goods_name" : "夏新N7", "createTime" : ISODate("2016-12-21T11:19:39.010Z") }
    { "goods_id" : 18, "goods_name" : "夏新T5", "createTime" : ISODate("2016-12-21T11:19:39.010Z") }
    { "goods_id" : 19, "goods_name" : "三星SGH-F258", "createTime" : ISODate("2016-12-21T11:19:39.010Z") }
    { "goods_id" : 20, "goods_name" : "三星BC01", "createTime" : ISODate("2016-12-21T11:19:39.010Z") }
    { "goods_id" : 2, "createTime" : ISODate("2015-10-01T00:00:00Z") }

    find

    find的第一个参数决定了要返回哪些文档,用于指定查询条件。要不指定查询文档,默认就是{},指定多个键/值对,相当于sqland。第二个参数来指定想要的键(默认情况下,"_id"总是显示)。

    查询条件

    And查询

    使用AND型查询时,应尽可能用最少的条件来限定结果的范围。

    > db.product.find({"goods_id":"4","goods_name":"诺基亚N85原装充电器"},{"_id":0})
    { "goods_id" : "4", "goods_name" : "诺基亚N85原装充电器", "createTime" : ISODate("2016-09-11T00:00:00Z") }

    当然也可以这样(纯属闲得蛋疼):

    > db.product.find({"$and":[{"goods_id":"4","goods_name":"诺基亚N85原装充电器"}]},{"_id":0})
    { "goods_id" : "4", "goods_name" : "诺基亚N85原装充电器", "createTime" : ISODate("2016-09-11T00:00:00Z") }

    Or查询

    方式一:$in$nin

    $in可以用来查询一个键的多个值,可以指定不同类型的条件和值。

    $nin将返回与数组中所有条件都不匹配的文档。

    $in是对单个键做OR查询。

    > db.product.find({"goods_id":{"$in":["4",5,6]}},{"_id":0})
    { "goods_id" : "4", "goods_name" : "诺基亚N85原装充电器", "createTime" : ISODate("2016-09-11T00:00:00Z") }
    { "goods_id" : 5, "goods_name" : "索爱原装M2卡读卡器", "createTime" : ISODate("2016-12-21T11:19:39.010Z") }
    { "goods_id" : 6, "goods_name" : "胜创KINGMAX内存卡", "createTime" : ISODate("2016-12-21T11:19:39.010Z") }
    > 

    方式二:$or

    $or更通用一些,可以在多个键中查询任意的给定值

    使用$or时,第一个条件条件应尽可能匹配更多的文档,这样才是最为高效的。

    > db.product.find({"$or":[{"goods_id":16},{"goods_name":"夏新T5"},{"createTime":{"$lt":new Date("2016-01-01")}}]},{"_id":0})
    { "goods_id" : 16, "goods_name" : "恒基伟业G101", "createTime" : ISODate("2016-12-21T11:19:39.010Z") }
    { "goods_id" : 18, "goods_name" : "夏新T5", "createTime" : ISODate("2016-12-21T11:19:39.010Z") }
    { "goods_id" : 2, "createTime" : ISODate("2015-10-01T00:00:00Z") }

    $lt、 $lte、 $gt、 $gte、$eq(貌似没什么用)、$ne

    $lt$lte$gt$gte、$eq、$ne分别对应sql中的<<= >>=、=、!=。组合查找一个范围的值。

    > db.product.find({"goods_id":{"$gte":3,"$lt":5}},{"_id":0} )
    { "goods_id" : 3, "goods_name" : "诺基亚原装5800耳机", "createTime" : ISODate("2016-10-09T00:00:00Z") }
    > start=new Date("01/01/2016")
     ISODate("2015-12-31T16:00:00Z")
    
    > db.product.find({"createTime":{"$lt":start}})//查询指定日期之前的数据
    { "_id" : ObjectId("585a65d9a847c6d3a3ee1da5"), "goods_id" : 2, "createTime" : ISODate("2015-10-01T00:00:00Z") }

    限制

    查询使用上有些限制。传递给数据库的查询文档的值必须是常量。也就是说不能引用文档中其他键的值。

     db.product.find({"goods_id":this.goods_name}).pretty()

    $mod

    取模运算符,会将查询的值除以第一个给定值,若余数等于第二个给定的值则匹配成功。

    > db.product.find({"goods_id":{"$mod":[5,1]}},{"_id":0})
    { "goods_id" : 1, "goods_name" : "KD876", "createTime" : ISODate("2016-12-21T11:19:39.010Z") }
    { "goods_id" : 6, "goods_name" : "胜创KINGMAX内存卡", "createTime" : ISODate("2016-12-21T11:19:39.010Z") }
    { "goods_id" : 11, "goods_name" : "索爱C702c", "createTime" : ISODate("2016-12-21T11:19:39.010Z") }
    { "goods_id" : 16, "goods_name" : "恒基伟业G101", "createTime" : ISODate("2016-12-21T11:19:39.010Z") }
    > 

    $not

    $not是元条件句,即可以用在其他任何其他条件之上。查询和匹配的件相反的数据。

    $not与正则表达式联合使用时极为有用,用来查找那些与特定模式不匹配的文档。

    > db.product.find({"goods_id":{"$not":{"$mod":[5,1]}}},{"_id":0})
    { "goods_id" : "4", "goods_name" : "诺基亚N85原装充电器", "createTime" : ISODate("2016-09-11T00:00:00Z") }
    { "goods_id" : 3, "goods_name" : "诺基亚原装5800耳机", "createTime" : ISODate("2016-10-09T00:00:00Z") }
    { "goods_id" : 5, "goods_name" : "索爱原装M2卡读卡器", "createTime" : ISODate("2016-12-21T11:19:39.010Z") }
    { "goods_id" : 7, "goods_name" : "诺基亚N85", "createTime" : ISODate("2016-12-21T11:19:39.010Z") }
    { "goods_id" : 8, "goods_name" : "飞利浦9@9v", "createTime" : ISODate("2016-12-21T11:19:39.010Z") }
    { "goods_id" : 9, "goods_name" : "诺基亚E66", "createTime" : ISODate("2016-12-21T11:19:39.010Z") }
    { "goods_id" : "10", "goods_name" : "索爱C702c", "createTime" : ISODate("2016-12-21T11:19:39.010Z") }
    { "goods_id" : 12, "goods_name" : "摩托罗拉A810", "createTime" : ISODate("2016-12-21T11:19:39.010Z") }
    { "goods_id" : 13, "goods_name" : "诺基亚5320", "createTime" : ISODate("2016-12-21T11:19:39.010Z") }
    { "goods_id" : 14, "goods_name" : "诺基亚5800XM", "createTime" : ISODate("2016-12-21T11:19:39.010Z") }
    { "goods_id" : "15", "goods_name" : "摩托罗拉A810", "createTime" : ISODate("2016-12-21T11:19:39.010Z") }
    { "goods_id" : 17, "goods_name" : "夏新N7", "createTime" : ISODate("2016-12-21T11:19:39.010Z") }
    { "goods_id" : 18, "goods_name" : "夏新T5", "createTime" : ISODate("2016-12-21T11:19:39.010Z") }
    { "goods_id" : 19, "goods_name" : "三星SGH-F258", "createTime" : ISODate("2016-12-21T11:19:39.010Z") }
    { "goods_id" : 20, "goods_name" : "三星BC01", "createTime" : ISODate("2016-12-21T11:19:39.010Z") }
    { "goods_id" : 2, "createTime" : ISODate("2015-10-01T00:00:00Z") }

    条件语义

    在查询中,$lt在内层文档,而在更新中$inc则是外层文档的键。

    基本可以肯定:条件语句是内层文档的键,而修改器则是外层文档的键。

    一个键可以有任意多个条件,但是一个键不能对应多个更新修改器。

    有一些”元操作符”也位于外层文档中,比如$and$or$nor

    查询优化器不会$and进行优化,这与其他操作符不相同。

    特定类型的查询

    null

    null不仅会匹配某个键的值为null的文档,而且还会匹配不含这个键的文档。

    如果仅想匹配键值为null的文档,既要检查该键的值是否为null,还要通过$exists条件判断键值已存在。

    > db.product.update({"goods_id":2},{"$set":{"goods_name":null}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.product.find({"goods_name":null},{"_id":0})
    { "goods_id" : 2, "createTime" : ISODate("2015-10-01T00:00:00Z"), "goods_name" : null }
    > db.product.find({"goods_no":{"$in":[null],"$exists":true}},{"_id":0})

    正则表达式

    正则表达式能够灵活有效地匹配字符串,系统可以接收正则表达式标志i (忽略大小写),但不一定要有。

    MongoDB可以为前缀型正则表达式(比如:/^joey/)查询创建索引,所以这种类型的查询会非常高效。

    > db.product.find({"goods_name":/^三星/},{"_id":0})
    { "goods_id" : 19, "goods_name" : "三星SGH-F258", "createTime" : ISODate("2016-12-21T11:19:39.010Z") }
    { "goods_id" : 20, "goods_name" : "三星BC01", "createTime" : ISODate("2016-12-21T11:19:39.010Z") }

    正则表达式也可以匹配自身。

    > db.product.find({"goods_name":/baz/},{"_id":0})
    { "goods_id" : 3, "goods_name" : /baz/, "createTime" : ISODate("2016-10-09T00:00:00Z") }

    查询数组

    查询数组元素与查询标量值是一样的。

    > db.product.update({"goods_id":"10"},{"$push":{"goods_type":{"$each":["华为", "乐视", "小米"]}}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.product.find({"goods_type":"小米"},{"_id":0})
    { "goods_id" : "10", "goods_name" : "索爱C702c", "createTime" : ISODate("2016-12-21T11:19:39.010Z"), "goods_type" : [ "华为", "乐视", "小米" ] }

    $all

    通过多个元素来匹配数组,这样就会匹配一组元素。

    > db.product.update({"goods_id":20},{"$push":{"goods_type":{"$each":["三星", "苹果", "努比亚"]}}})> db.product.update({"goods_id":18},{"$push":{"goods_type":{"$each":["华为", "苹果", "魅族"]}}})
    
    > db.product.find({"goods_type":{"$all":["苹果","华为"]}},{"_id":0})
    { "goods_id" : 18, "goods_name" : "夏新T5", "createTime" : ISODate("2016-12-21T11:19:39.010Z"), "goods_type" : [ "华为", "苹果", "魅族" ] }

    当然也可以使用整个数组进行精确匹配。但是,精确匹配必须一模一样的才查的出来,比如顺序,个数都得一样。

    > db.product.find({"goods_type":["华为","苹果","魅族"]},{"_id":0})
    { "goods_id" : 18, "goods_name" : "夏新T5", "createTime" : ISODate("2016-12-21T11:19:39.010Z"), "goods_type" : [ "华为", "苹果", "魅族" ] }

    查找特定位置的元素

    要想查询数组特定位置的元素,需使用key.index语法指定下标,数组下标都是从0开始的。

    > db.product.find({"goods_type.1":"苹果"},{"_id":0})
    { "goods_id" : 18, "goods_name" : "夏新T5", "createTime" : ISODate("2016-12-21T11:19:39.010Z"), "goods_type" : [ "华为", "苹果", "魅族" ] }
    { "goods_id" : 20, "goods_name" : "三星BC01", "createTime" : ISODate("2016-12-21T11:19:39.010Z"), "goods_type" : [ "三星", "苹果", "努比亚" ] }
    > 

    $size

    $size查询特定长度的数组

    > db.product.find({"goods_type":{"$size":3}},{"_id":0})
    { "goods_id" : "10", "goods_name" : "索爱C702c", "createTime" : ISODate("2016-12-21T11:19:39.010Z"), "goods_type" : [ "华为", "乐视", "小米" ] }
    { "goods_id" : 18, "goods_name" : "夏新T5", "createTime" : ISODate("2016-12-21T11:19:39.010Z"), "goods_type" : [ "华为", "苹果", "魅族" ] }
    { "goods_id" : 20, "goods_name" : "三星BC01", "createTime" : ISODate("2016-12-21T11:19:39.010Z"), "goods_type" : [ "三星", "苹果", "努比亚" ] }
    > 

    $slice

    $slice操作符可以返回某个键匹配的数组元素的一个子集。这个操作符是用来获取数组的前几个或者后几个元素,对整个数据进行过滤没有作用(比如: db.product.find({},{"goods_type":{"$slice":2}}) 会返回文档的所有数据

    > db.product.find({"goods_type":{"$size":3}},{"goods_type":{"$slice":-2},"_id":0})
    { "goods_id" : "10", "goods_name" : "索爱C702c", "createTime" : ISODate("2016-12-21T11:19:39.010Z"), "goods_type" : [ "乐视", "小米" ] }
    { "goods_id" : 18, "goods_name" : "夏新T5", "createTime" : ISODate("2016-12-21T11:19:39.010Z"), "goods_type" : [ "苹果", "魅族" ] }
    { "goods_id" : 20, "goods_name" : "三星BC01", "createTime" : ISODate("2016-12-21T11:19:39.010Z"), "goods_type" : [ "苹果", "努比亚" ] }
    > db.product.find({"goods_type":{"$size":3}},{"goods_type":{"$slice":2},"_id":0})
    { "goods_id" : "10", "goods_name" : "索爱C702c", "createTime" : ISODate("2016-12-21T11:19:39.010Z"), "goods_type" : [ "华为", "乐视" ] }
    { "goods_id" : 18, "goods_name" : "夏新T5", "createTime" : ISODate("2016-12-21T11:19:39.010Z"), "goods_type" : [ "华为", "苹果" ] }
    { "goods_id" : 20, "goods_name" : "三星BC01", "createTime" : ISODate("2016-12-21T11:19:39.010Z"), "goods_type" : [ "三星", "苹果" ] }
    > 

    $slice也可以指定偏移值以及希望返回的元素数量,来返回元素集合中间位置的某些结果。

    > db.product.find({"goods_type":{"$size":3}},{"goods_type":{"$slice":[1,1]},"_id":0})//跳过1个,取1个
    { "goods_id" : "10", "goods_name" : "索爱C702c", "createTime" : ISODate("2016-12-21T11:19:39.010Z"), "goods_type" : [ "乐视" ] }
    { "goods_id" : 18, "goods_name" : "夏新T5", "createTime" : ISODate("2016-12-21T11:19:39.010Z"), "goods_type" : [ "苹果" ] }
    { "goods_id" : 20, "goods_name" : "三星BC01", "createTime" : ISODate("2016-12-21T11:19:39.010Z"), "goods_type" : [ "苹果" ] }

    返回一个匹配的数组元素

    $ 返回与查询条件相匹配的任意一个数组元素。只会返回第一个匹配的文档。

    > db.blog.find({"comments.votes":3}).pretty()
    {
            "_id" : ObjectId("585694e4c5b0525a48a441b5"),
            "content" : "...",
            "comments" : [
                    {
                            "comment" : "good post",
                            "author" : "jim",
                            "votes" : 1
                    },
                    {
                            "comment" : "i thought it was too short",
                            "author" : "claire",
                            "votes" : 3
                    },
                    {
                            "comment" : "free watches",
                            "author" : "alice",
                            "votes" : 3
                    }
            ]
    }
    > 
    > db.blog.find({"comments.votes":3},{"comments.$":1}).pretty()
    {
            "_id" : ObjectId("585694e4c5b0525a48a441b5"),
            "comments" : [
                    {
                            "comment" : "i thought it was too short",
                            "author" : "claire",
                            "votes" : 3
                    }
            ]
    }

    数组和范围查询的相互作用

    文档中的标量(非数组元素)必须与查询条件中的每一条语句相匹配。比如,如果使用 {"$gt":10,"$lt":20} 进行查询,只会匹配x键的值大于10并且小于20的文档。

    但是,假如某个文档的x字段是一个数组,如果x键的某一个元素与查询条件得到任意一条语句相匹配,那么这个文档也会被返回。

    { "_id" : ObjectId("585d404b53fe663a4c5c202e"), "x" : 5 }
    { "_id" : ObjectId("585d404b53fe663a4c5c202f"), "x" : 15 }
    { "_id" : ObjectId("585d404b53fe663a4c5c2030"), "x" : 25 }
    { "_id" : ObjectId("585d404b53fe663a4c5c2031"), "x" : [ 5, 25 ] }
    > db.foo.find({"x":{"$gt":5,"$lt":20}})
    { "_id" : ObjectId("585d404b53fe663a4c5c202f"), "x" : 15 }
    { "_id" : ObjectId("585d404b53fe663a4c5c2031"), "x" : [ 5, 25 ] }

    上述方式对数组使用范围查询没有用:范围会匹配任意多个元素数组。有几种方式可以得到预期的结果。

    方式1:$elemMatch

    $elemMatch要求MongoDB同时使用查询条件中的两个语句与一个数组元素进行比较。但是,它不会匹配非数组元素。

    > db.foo.find({"x":{"$elemMatch":{"$gt":10,"$lt":20}}})
    > 

    方式2:使用min()和max()

    如果当前查询的字段上创建过索引,可以使用min()max()将查询条件遍历的索引范围限制为”$gt”和”$lt”的值。而且,必须为这个索引的所有字段指定min()max().

    > db.foo.find({"x":{"$gt":10,"$lt":20}}).min({"x":10}).max({"x":20})
  • 相关阅读:
    @FeignClient常用属性
    前端调用接口成功但后端没收到请求
    @EnableDiscoveryClient与Nacos的服务注册与拉取
    解决WebStorm开发vue提示Module is not installed、Unresolved variable or type
    Docker内使用Nignx
    Docker内运行的nginx除了80端口其他端口都无法访问
    在Win11的WSL中体验IDEA等GUI程序
    python小工具:编码转换
    php nginx 504 Gateway Timeout 网关超时错误
    Centos下安装php mysql pdo以及gd扩展
  • 原文地址:https://www.cnblogs.com/ginb/p/6200721.html
Copyright © 2020-2023  润新知