MongoDB-非常详细版增删改查(看这一篇就够了)

前言

本篇章主要介绍MongoDB的一些增删改查的操作,从简入深,其中主要包括了MongoDB多种查询方式,和返回结果的配置以及一些简单的聚合管道查询,MongoDB的命令形式都是以json的格式进行的,比起关系型数据的标准化SQL语句,稍微有些不同,要想知道具体如何实现,请君往下看。

MongoDB之insert插入

1.MongoDB使用use命令进入到一个数据库中。如果use的数据库不存在则会自动创建这个数据库,但是如果没有在数据库中插入数据,那这个数据库也不会被实际创建。

MongoDB Enterprise test:PRIMARY> use mongodb_test
...
switched to db mongodb_test
MongoDB Enterprise test:PRIMARY> show dbs
...
admin   0.000GB
config  0.000GB
local   0.000GB
###通过db.mongodb_test.insert语句向mongodb_test数据库插入一条数据后,再show dbs就会发现数据库被真正创建了。
MongoDB Enterprise test:PRIMARY> db.mongodb_test.insert({test:123});
...
WriteResult({ "nInserted" : 1 })
###insertOne与insert效果一样,只是返回结果会返回ObjectId字段。
MongoDB Enterprise test:PRIMARY> db.mongodb_test.insertOne({id1:1});
...
{
        "acknowledged" : true,
        "insertedId" : ObjectId("66d580480d68103de341fe76")
}
MongoDB Enterprise test:PRIMARY> show dbs
...
admin         0.000GB
config        0.000GB
local         0.000GB
mongodb_test  0.000GB

小知识:自动生成的字段_id,在 MongoDB 中,存储在集合中的每个文档都需要一个唯一的 _id 字段作为主键。如果插入的文档省略了 _id 字段,MongoDB 驱动程序会自动为 ObjectId 字段生成一个 _id。

2.上方提到的db.mongodb_test.insert这种语句方式只能插入一条数据,如果要是想插入多条数据可以使用insertMany

MongoDB Enterprise test:PRIMARY> db.db.mongodb_test.insertMany([{id1:1},{id2:2},{id3:3}]);
...
{
        "acknowledged" : true,
        "insertedIds" : [
                ObjectId("66d578890d68103de341fe73"),
...

MongoDB之find查询

1.直接使用find查询所有数据

###查询刚才我们插入的数据
MongoDB Enterprise test:PRIMARY> db.mongodb_test.find( {} );
...
{ "_id" : ObjectId("66d580480d68103de341fe76"), "id1" : 1 }
{ "_id" : ObjectId("66d5847e0d68103de341fe7f"), "id1" : 1 }
{ "_id" : ObjectId("66d5847e0d68103de341fe80"), "id2" : 2 }
{ "_id" : ObjectId("66d5847e0d68103de341fe81"), "id3" : 3 }

2.使用find进行过滤查询

MongoDB Enterprise test:PRIMARY> db.mongodb_test.find( {"id1":1} );
...
{ "_id" : ObjectId("66d580480d68103de341fe76"), "id1" : 1 }
{ "_id" : ObjectId("66d5847e0d68103de341fe7f"), "id1" : 1 }

find使用运算符过滤查询

1.使用find的运算符in进行查询

###然后对inventory插入一批数据,功我们查询
MongoDB Enterprise test:PRIMARY>db.inventory.insertMany([
   { item: "journal", qty: 25, size: { h: 14, w: 21, uom: "cm" }, status: "A" },
   { item: "notebook", qty: 50, size: { h: 8.5, w: 11, uom: "in" }, status: "A" },
   { item: "paper", qty: 100, size: { h: 8.5, w: 11, uom: "in" }, status: "D" },
   { item: "planner", qty: 75, size: { h: 22.85, w: 30, uom: "cm" }, status: "D" },
   { item: "postcard", qty: 45, size: { h: 10, w: 15.25, uom: "cm" }, status: "A" }
]);
###查询所有status为A、和D的数据
MongoDB Enterprise test:PRIMARY> db.inventory.find( { status: { $in: [ "A", "D" ] } } );
...
{ "_id" : ObjectId("66d583ff0d68103de341fe77"), "item" : "journal", "qty" : 25, "size" : { "h" : 14, "w" : 21, "uom" : "cm" }, "status" : "A" }
{ "_id" : ObjectId("66d583ff0d68103de341fe78"), "item" : "notebook", "qty" : 50, "size" : { "h" : 8.5, "w" : 11, "uom" : "in" }, "status" : "A" }
{ "_id" : ObjectId("66d583ff0d68103de341fe79"), "item" : "paper", "qty" : 100, "size" : { "h" : 8.5, "w" : 11, "uom" : "in" }, "status" : "D" }
...

小知识:如果当插入的集合不存在的话,会自动创建集合并进行插入,比如上方我们并没有创建inventory,也可以进行插入。

2.使用运算符and进行查询

#这里的语句使用到了$lt表示小于的意思,查询status为A的数据,并且qty小于30。
MongoDB Enterprise test:PRIMARY> db.inventory.find({status:"A",qty:{$lt:30}});
...
{ "_id" : ObjectId("66d583ff0d68103de341fe77"), "item" : "journal", "qty" : 25, "size" : { "h" : 14, "w" : 21, "uom" : "cm" }, "status" : "A" }

3.使用运算符or进行查询

###这里使用到了$or表示查询status为D或者qty小于30的数据
MongoDB Enterprise test:PRIMARY> db.inventory.find({$or:[{status:"D"},{qty:{$lt:30}}]});
...
{ "_id" : ObjectId("66d583ff0d68103de341fe77"), "item" : "journal", "qty" : 25, "size" : { "h" : 14, "w" : 21, "uom" : "cm" }, "status" : "A" }
{ "_id" : ObjectId("66d583ff0d68103de341fe79"), "item" : "paper", "qty" : 100, "size" : { "h" : 8.5, "w" : 11, "uom" : "in" }, "status" : "D" }
{ "_id" : ObjectId("66d583ff0d68103de341fe7a"), "item" : "planner", "qty" : 75, "size" : { "h" : 22.85, "w" : 30, "uom" : "cm" }, "status" : "D" }

4.上点难度,使用运算符and和or以及in进行查询

###这里的语句含义为,查询status为A和D的数据,或者qty小于10,或者item为p开头的。
MongoDB Enterprise test:PRIMARY> db.inventory.find({status:{$in: ["A","D"]},$or:[{qty:{$lt:10}},{item:/^p/}]});
...
{ "_id" : ObjectId("66d583ff0d68103de341fe79"), "item" : "paper", "qty" : 100, "size" : { "h" : 8.5, "w" : 11, "uom" : "in" }, "status" : "D" }
{ "_id" : ObjectId("66d583ff0d68103de341fe7a"), "item" : "planner", "qty" : 75, "size" : { "h" : 22.85, "w" : 30, "uom" : "cm" }, "status" : "D" }
{ "_id" : ObjectId("66d583ff0d68103de341fe7b"), "item" : "postcard", "qty" : 45, "size" : { "h" : 10, "w" : 15.25, "uom" : "cm" }, "status" : "A" }

find查询嵌套类型的数据

  • 嵌套查询顾名思义,就是查询我们集合中,某个列,文档内部或者说数组内部的列或者也叫key。

1.使用size.h这样的方式,表示查询的是size这个列下面h这个key。

###查询size列下面的h这个key为14的值的数据有哪些。
MongoDB Enterprise test:PRIMARY> db.inventory.find( { "size.h": 14 } )
...
{ "_id" : ObjectId("66d583ff0d68103de341fe77"), "item" : "journal", "qty" : 25, "size" : { "h" : 14, "w" : 21, "uom" : "cm" }, "status" : "A" }

2.使用运算符进行嵌套查询

###此处表示查询inventory下,size这个key中的h这个key,值为14和8.5的数据有哪些。
MongoDB Enterprise test:PRIMARY> db.inventory.find( { "size.h":{$in:[14,8.5]} } )
...
{ "_id" : ObjectId("66d583ff0d68103de341fe77"), "item" : "journal", "qty" : 25, "size" : { "h" : 14, "w" : 21, "uom" : "cm" }, "status" : "A" }
{ "_id" : ObjectId("66d583ff0d68103de341fe78"), "item" : "notebook", "qty" : 50, "size" : { "h" : 8.5, "w" : 11, "uom" : "in" }, "status" : "A" }
{ "_id" : ObjectId("66d583ff0d68103de341fe79"), "item" : "paper", "qty" : 100, "size" : { "h" : 8.5, "w" : 11, "uom" : "in" }, "status" : "D" }

find查询数组类型的数据

  • 我们MongoDB中存储的不只有嵌套的文档,还有数组,下面我们来看下数组是怎么进行查询的。

1.清理之前的数据,并插入一些数组类型的数据。

MongoDB Enterprise test:PRIMARY>  db.inventory.remove()
MongoDB Enterprise test:PRIMARY>  db.inventory.insertMany([
   { item: "journal", qty: 25, tags: ["blank", "red"], dim_cm: [ 14, 21 ] },
   { item: "notebook", qty: 50, tags: ["red", "blank"], dim_cm: [ 14, 21 ] },
   { item: "paper", qty: 100, tags: ["red", "blank", "plain"], dim_cm: [ 14, 21 ] },
   { item: "planner", qty: 75, tags: ["blank", "red"], dim_cm: [ 22.85, 30 ] },
   { item: "postcard", qty: 45, tags: ["blue"], dim_cm: [ 10, 15.25 ] }
]);
...

小知识:一般情况{}包括的内容为文档,[]包括的内容为数组。

2.查询数组当中的数据。

###以下语句表示,查询inventory集合当中,tags这个key数组为["blank","red"]的值有哪些。
MongoDB Enterprise test:PRIMARY> db.inventory.find({tags:["blank","red"]});
...
{ "_id" : ObjectId("66d590ae0d68103de341fe82"), "item" : "journal", "qty" : 25, "tags" : [ "blank", "red" ], "dim_cm" : [ 14, 21 ] }
{ "_id" : ObjectId("66d590ae0d68103de341fe85"), "item" : "planner", "qty" : 75, "tags" : [ "blank", "red" ], "dim_cm" : [ 22.85, 30 ] }

###上方的发现是严格按照数组列表中的顺序进行查询的,如果想不按照顺序,就是查数组中包含哪些数据,忽略顺序,可以使用到$all这个函数。
MongoDB Enterprise test:PRIMARY> db.inventory.find({tags:{$all:["blank","red"]}});
...
{ "_id" : ObjectId("66d590ae0d68103de341fe82"), "item" : "journal", "qty" : 25, "tags" : [ "blank", "red" ], "dim_cm" : [ 14, 21 ] }
{ "_id" : ObjectId("66d590ae0d68103de341fe83"), "item" : "notebook", "qty" : 50, "tags" : [ "red", "blank" ], "dim_cm" : [ 14, 21 ] }
{ "_id" : ObjectId("66d590ae0d68103de341fe84"), "item" : "paper", "qty" : 100, "tags" : [ "red", "blank", "plain" ], "dim_cm" : [ 14, 21 ] }
{ "_id" : ObjectId("66d590ae0d68103de341fe85"), "item" : "planner", "qty" : 75, "tags" : [ "blank", "red" ], "dim_cm" : [ 22.85, 30 ] }

3.查询数组中的元素

###以下语句查询了,tags这个key,数组当中包含red这个元素的数据有哪些。
MongoDB Enterprise test:PRIMARY> db.inventory.find( { tags: "blank" } )
...
{ "_id" : ObjectId("66d590ae0d68103de341fe82"), "item" : "journal", "qty" : 25, "tags" : [ "blank", "red" ], "dim_cm" : [ 14, 21 ] }
{ "_id" : ObjectId("66d590ae0d68103de341fe83"), "item" : "notebook", "qty" : 50, "tags" : [ "red", "blank" ], "dim_cm" : [ 14, 21 ] }
{ "_id" : ObjectId("66d590ae0d68103de341fe84"), "item" : "paper", "qty" : 100, "tags" : [ "red", "blank", "plain" ], "dim_cm" : [ 14, 21 ] }
{ "_id" : ObjectId("66d590ae0d68103de341fe85"), "item" : "planner", "qty" : 75, "tags" : [ "blank", "red" ], "dim_cm" : [ 22.85, 30 ] }

4.为数组中元素增加条件查询

###下方语句表示查询inventory集合中,dim_cm这个字段数组元素大于21的有哪些。
MongoDB Enterprise test:PRIMARY> db.inventory.find( { dim_cm:{$gt:21} } )
{ "_id" : ObjectId("66d590ae0d68103de341fe85"), "item" : "planner", "qty" : 75, "tags" : [ "blank", "red" ], "dim_cm" : [ 22.85, 30 ] }

5.为数组增加多个条件进行查询

###这里表示查询inventory集合中dim_cm列这个数组中大于20小于21的有哪些数据。
MongoDB Enterprise test:PRIMARY> db.inventory.find({dim_cm:{$gt:20,$lt:21}})
...
{ "_id" : ObjectId("66d65de9ed7c51952d84a63c"), "item" : "journal", "qty" : 25, "tags" : [ "blank", "red" ], "dim_cm" : [ 14, 21 ] }
{ "_id" : ObjectId("66d65de9ed7c51952d84a63d"), "item" : "notebook", "qty" : 50, "tags" : [ "red", "blank" ], "dim_cm" : [ 14, 21 ] }
{ "_id" : ObjectId("66d65de9ed7c51952d84a63e"), "item" : "paper", "qty" : 100, "tags" : [ "red", "blank", "plain" ], "dim_cm" : [ 14, 21 ] }

6.使用$elemMatch函数查询数组。使用这个函数就需要数组内满足指定的所有条件。

###这里表示,dim_cm数组中,至少有一个大于22并且小于30的元素。
MongoDB Enterprise test:PRIMARY> db.inventory.find( { dim_cm: { $elemMatch: { $gt: 22, $lt: 30 } } } )
...
{ "_id" : ObjectId("66d65de9ed7c51952d84a63f"), "item" : "planner", "qty" : 75, "tags" : [ "blank", "red" ], "dim_cm" : [ 22.85, 30 ] }

7.按照数组中的索引位置,进行条件匹配查询

###这里的"dim_cm.0"表示的是dim_cm索引的第一个元素,1表示第二个,以此类推。
MongoDB Enterprise test:PRIMARY> db.inventory.find( { "dim_cm.0": { $gt: 14 } } )
...
{ "_id" : ObjectId("66d65de9ed7c51952d84a63f"), "item" : "planner", "qty" : 75, "tags" : [ "blank", "red" ], "dim_cm" : [ 22.85, 30 ] }

8.根据数组的长度进行查询

###使用size函数查询tags中,有三个和两个元素的行有哪些。
MongoDB Enterprise test:PRIMARY> db.inventory.find( { "tags": { $size: 3 } } )
{ "_id" : ObjectId("66d65de9ed7c51952d84a63e"), "item" : "paper", "qty" : 100, "tags" : [ "red", "blank", "plain" ], "dim_cm" : [ 14, 21 ] }
MongoDB Enterprise test:PRIMARY> db.inventory.find( { "tags": { $size: 2 } } )
{ "_id" : ObjectId("66d65de9ed7c51952d84a63c"), "item" : "journal", "qty" : 25, "tags" : [ "blank", "red" ], "dim_cm" : [ 14, 21 ] }
{ "_id" : ObjectId("66d65de9ed7c51952d84a63d"), "item" : "notebook", "qty" : 50, "tags" : [ "red", "blank" ], "dim_cm" : [ 14, 21 ] }
{ "_id" : ObjectId("66d65de9ed7c51952d84a63f"), "item" : "planner", "qty" : 75, "tags" : [ "blank", "red" ], "dim_cm" : [ 22.85, 30 ] }

find查询嵌套式文档数组

1.清理之前的数据,插入新数据

MongoDB Enterprise test:PRIMARY>  db.inventory.remove()
MongoDB Enterprise test:PRIMARY> db.inventory.insertMany( [
   { item: "journal", instock: [ { warehouse: "A", qty: 5 }, { warehouse: "C", qty: 15 } ] },
   { item: "notebook", instock: [ { warehouse: "C", qty: 5 } ] },
   { item: "paper", instock: [ { warehouse: "A", qty: 60 }, { warehouse: "B", qty: 15 } ] },
   { item: "planner", instock: [ { warehouse: "A", qty: 40 }, { warehouse: "B", qty: 5 } ] },
   { item: "postcard", instock: [ { warehouse: "B", qty: 15 }, { warehouse: "C", qty: 35 } ] }
]);

2.查询数组嵌套中的文档

#查询instock这个数组中包含{ warehouse: "A", qty: 5 } 的文档。
MongoDB Enterprise test:PRIMARY> db.inventory.find( { "instock": { warehouse: "A", qty: 5 } } )
...
{ "_id" : ObjectId("66d6654eed7c51952d84a641"), "item" : "journal", "instock" : [ { "warehouse" : "A", "qty" : 5 }, { "warehouse" : "C", "qty" : 15 } ] }

小知识:整个嵌入式/嵌套文档的相等匹配要求与指定文档精确匹配,包括字段和顺序。

3.如果不知道嵌套文档中的索引位置,可以使用.qty方式查询嵌套文档中的字段key,下面使用$lte函数,查询嵌套文档中,qty这个key的值小于或等于5的有哪些。一行数据至少包含一个小于5的值才可以返回。

MongoDB Enterprise test:PRIMARY> db.inventory.find( { 'instock.qty': { $lte: 6 } } )
...
{ "_id" : ObjectId("66d6654eed7c51952d84a641"), "item" : "journal", "instock" : [ { "warehouse" : "A", "qty" : 5 }, { "warehouse" : "C", "qty" : 15 } ] }
{ "_id" : ObjectId("66d6654eed7c51952d84a642"), "item" : "notebook", "instock" : [ { "warehouse" : "C", "qty" : 5 } ] }
{ "_id" : ObjectId("66d6654eed7c51952d84a644"), "item" : "planner", "instock" : [ { "warehouse" : "A", "qty" : 40 }, { "warehouse" : "B", "qty" : 5 } ] }

4.使用数组索引查询嵌套文档中的字段内容

###下方语句表示,查询inventory集合,instock索引位置为0,也就是第一个元素的qty小于等于6的有哪些。
MongoDB Enterprise test:PRIMARY> db.inventory.find( { 'instock.0.qty': { $lte: 6 } } )
...
{ "_id" : ObjectId("66d6654eed7c51952d84a641"), "item" : "journal", "instock" : [ { "warehouse" : "A", "qty" : 5 }, { "warehouse" : "C", "qty" : 15 } ] }
{ "_id" : ObjectId("66d6654eed7c51952d84a642"), "item" : "notebook", "instock" : [ { "warehouse" : "C", "qty" : 5 } ] }

5.使用多条件匹配查询数组中嵌套文档中的数据

###下方又使用到了$elemMatch函数,表示多条件匹配,必须有一条满足指定的所有条件。下方表示查询inventory集合instock数组中,qty为15并且warehouse为B的数据
MongoDB Enterprise test:PRIMARY> db.inventory.find( { "instock": { $elemMatch: { qty: 15, warehouse: "B" } } } )
...
{ "_id" : ObjectId("66d6654eed7c51952d84a643"), "item" : "paper", "instock" : [ { "warehouse" : "A", "qty" : 60 }, { "warehouse" : "B", "qty" : 15 } ] }
{ "_id" : ObjectId("66d6654eed7c51952d84a645"), "item" : "postcard", "instock" : [ { "warehouse" : "B", "qty" : 15 }, { "warehouse" : "C", "qty" : 35 } ] }

###下方查询表示,查询inventory集合instock数组中,qty大于10并且小于15的有哪些数据。
MongoDB Enterprise test:PRIMARY> db.inventory.find( { "instock": { $elemMatch: { qty: { $gt: 10, $lte: 15 } } } } )
...
{ "_id" : ObjectId("66d6654eed7c51952d84a641"), "item" : "journal", "instock" : [ { "warehouse" : "A", "qty" : 5 }, { "warehouse" : "C", "qty" : 15 } ] }
{ "_id" : ObjectId("66d6654eed7c51952d84a643"), "item" : "paper", "instock" : [ { "warehouse" : "A", "qty" : 60 }, { "warehouse" : "B", "qty" : 15 } ] }
{ "_id" : ObjectId("66d6654eed7c51952d84a645"), "item" : "postcard", "instock" : [ { "warehouse" : "B", "qty" : 15 }, { "warehouse" : "C", "qty" : 35 } ] }

6.不使用$elemMatch函数,组合满足标准的元素查询

  • 下方可以看到没有使用elemMatch函数和使用后相差了一行数据,这就是需要同时满足查询条件和只需满足一个查询条件的区别。不加elemMatch表示同一行数据中,大于10的并且小于20的数据存在即可。下方的相差数据,第一个文档中的40满足大于10的条件,第二个文档中满足小于20的条件。而加上elemMatch需要有一个数据同时满足大于10并且小于20才可以返回。很明显40和5这两个数字都不能满足。
MongoDB Enterprise test:PRIMARY> db.inventory.find( { "instock.qty": { $gt: 10,  $lte: 20 } } )
{ "_id" : ObjectId("66d6654eed7c51952d84a641"), "item" : "journal", "instock" : [ { "warehouse" : "A", "qty" : 5 }, { "warehouse" : "C", "qty" : 15 } ] }
{ "_id" : ObjectId("66d6654eed7c51952d84a643"), "item" : "paper", "instock" : [ { "warehouse" : "A", "qty" : 60 }, { "warehouse" : "B", "qty" : 15 } ] }
{ "_id" : ObjectId("66d6654eed7c51952d84a644"), "item" : "planner", "instock" : [ { "warehouse" : "A", "qty" : 40 }, { "warehouse" : "B", "qty" : 5 } ] }
{ "_id" : ObjectId("66d6654eed7c51952d84a645"), "item" : "postcard", "instock" : [ { "warehouse" : "B", "qty" : 15 }, { "warehouse" : "C", "qty" : 35 } ] }
...
MongoDB Enterprise test:PRIMARY> db.inventory.find( { "instock": { $elemMatch: { qty: { $gt: 10, $lte: 20 } } } } )
{ "_id" : ObjectId("66d6654eed7c51952d84a641"), "item" : "journal", "instock" : [ { "warehouse" : "A", "qty" : 5 }, { "warehouse" : "C", "qty" : 15 } ] }
{ "_id" : ObjectId("66d6654eed7c51952d84a643"), "item" : "paper", "instock" : [ { "warehouse" : "A", "qty" : 60 }, { "warehouse" : "B", "qty" : 15 } ] }
{ "_id" : ObjectId("66d6654eed7c51952d84a645"), "item" : "postcard", "instock" : [ { "warehouse" : "B", "qty" : 15 }, { "warehouse" : "C", "qty" : 35 } ] }

find查询返回结果设置

  • 通过上方的查询可以看到,我们查询的数据,返回的都是整行数据的所有字段,但很多时候,我们只需要返回一行数据中的一两个字段就够了。就好比之前我们的查询都是"select *",现在我们来学习以下如何让MongoDB,像SQL一样,执行"select id,name"这样根据我们需要的字段返回结果。

1.清理之前的测试数据,并插入新的数据

MongoDB Enterprise test:PRIMARY>  db.inventory.remove()
MongoDB Enterprise test:PRIMARY>  db.inventory.insertMany( [
  { item: "journal", status: "A", size: { h: 14, w: 21, uom: "cm" }, instock: [ { warehouse: "A", qty: 5 } ] },
  { item: "notebook", status: "A",  size: { h: 8.5, w: 11, uom: "in" }, instock: [ { warehouse: "C", qty: 5 } ] },
  { item: "paper", status: "D", size: { h: 8.5, w: 11, uom: "in" }, instock: [ { warehouse: "A", qty: 60 } ] },
  { item: "planner", status: "D", size: { h: 22.85, w: 30, uom: "cm" }, instock: [ { warehouse: "A", qty: 40 } ] },
  { item: "postcard", status: "A", size: { h: 10, w: 15.25, uom: "cm" }, instock: [ { warehouse: "B", qty: 15 }, { warehouse: "C", qty: 35 } ] }
]);

2.查询status字段为D的值,并且只返回status字段和size字段。

###只需要在查询条件的后方增加{status:1,size:1})即可。
MongoDB Enterprise test:PRIMARY> db.inventory.find({status:"D"},{status:1,size:1})
...
{ "_id" : ObjectId("66d6a278b0fe1d39d3045152"), "status" : "D", "size" : { "h" : 8.5, "w" : 11, "uom" : "in" } }
{ "_id" : ObjectId("66d6a278b0fe1d39d3045153"), "status" : "D", "size" : { "h" : 22.85, "w" : 30, "uom" : "cm" } }

3.通过上方的查询可以看到,有个自动生成的_id字段也会自动显示。下面我们抑制_id字段。

###通过_id:0就可以不再显示_id这个字段
MongoDB Enterprise test:PRIMARY> db.inventory.find({status:"D"},{status:1,size:1,_id:0})
{ "status" : "D", "size" : { "h" : 8.5, "w" : 11, "uom" : "in" } }
{ "status" : "D", "size" : { "h" : 22.85, "w" : 30, "uom" : "cm" } }

4.有的时候我们需要看的字段是很多,但是知道哪些不用看,所以就是返回结果,除了排除字段以外的所有字段。

MongoDB Enterprise test:PRIMARY> db.inventory.find( { status: "A" }, { _id: 0 } )
...
{ "item" : "journal", "status" : "A", "size" : { "h" : 14, "w" : 21, "uom" : "cm" }, "instock" : [ { "warehouse" : "A", "qty" : 5 } ] }
{ "item" : "notebook", "status" : "A", "size" : { "h" : 8.5, "w" : 11, "uom" : "in" }, "instock" : [ { "warehouse" : "C", "qty" : 5 } ] }
{ "item" : "postcard", "status" : "A", "size" : { "h" : 10, "w" : 15.25, "uom" : "cm" }, "instock" : [ { "warehouse" : "B", "qty" : 15 }, { "warehouse" : "C", "qty" : 35 } ] }

小知识:上面表示除了_id字段不显示,其余的字段都显示,其实到了这里大家都看明白了,如果字段配置1那就只显示这个字段,如果字段配置0那么就是除了这个字段其余的都显示。除 _id 字段之外,因为_id字段如果不抑制默认显示。

5.设置嵌套数组中返回的字段

###这里就需要指定嵌套文档字段和嵌套中的字段了。要用双引号"instock.qty":1
MongoDB Enterprise test:PRIMARY> db.inventory.find( { status: "A" }, {status:1,"instock.qty":1} )
...
{ "_id" : ObjectId("66d6a278b0fe1d39d3045150"), "status" : "A", "instock" : [ { "qty" : 5 } ] }
{ "_id" : ObjectId("66d6a278b0fe1d39d3045151"), "status" : "A", "instock" : [ { "qty" : 5 } ] }
{ "_id" : ObjectId("66d6a278b0fe1d39d3045154"), "status" : "A", "instock" : [ { "qty" : 15 }, { "qty" : 35 } ] }

###抑制嵌套数组中的字段
MongoDB Enterprise test:PRIMARY> db.inventory.find( { status: "A" }, {"instock.qty":0} )
...
{ "_id" : ObjectId("66d6a278b0fe1d39d3045150"), "item" : "journal", "status" : "A", "size" : { "h" : 14, "w" : 21, "uom" : "cm" }, "instock" : [ { "warehouse" : "A" } ] }
{ "_id" : ObjectId("66d6a278b0fe1d39d3045151"), "item" : "notebook", "status" : "A", "size" : { "h" : 8.5, "w" : 11, "uom" : "in" }, "instock" : [ { "warehouse" : "C" } ] }
{ "_id" : ObjectId("66d6a278b0fe1d39d3045154"), "item" : "postcard", "status" : "A", "size" : { "h" : 10, "w" : 15.25, "uom" : "cm" }, "instock" : [ { "warehouse" : "B" }, { "warehouse" : "C" } ] }

###通过函数$slice:设置返回字段,这个函数表示要返回数组中的哪个索引位置的数据下方的-1表示,倒数第一个。
MongoDB Enterprise test:PRIMARY> db.inventory.find( { status: "A" }, { item: 1, status: 1, instock: { $slice: -1 } } )
...
{ "_id" : ObjectId("66d6a278b0fe1d39d3045150"), "item" : "journal", "status" : "A", "instock" : [ { "warehouse" : "A", "qty" : 5 } ] }
{ "_id" : ObjectId("66d6a278b0fe1d39d3045151"), "item" : "notebook", "status" : "A", "instock" : [ { "warehouse" : "C", "qty" : 5 } ] }
{ "_id" : ObjectId("66d6a278b0fe1d39d3045154"), "item" : "postcard", "status" : "A", "instock" : [ { "warehouse" : "C", "qty" : 35 } ] }

通过聚合表达式查询数据

db.inventory.find(
   { },
   {
      _id: 0, #不显示_id列
      item: 1,#显示item列
      status: {
         $switch: { #对status列做case表达式
            branches: [
               {
                  case: { $eq: [ "$status", "A" ] },#判断status是否为A如果是则返回Available
                  then: "Available"
               },
               {
                  case: { $eq: [ "$status", "D" ] },#判断status是否为D如果是则返回Discontinued
                  then: "Discontinued"
               },
            ],
            default: "No status found" #不为A和不为D则返回"No status found" 
         }
      },
      area: {#新的列名
         $concat: [ #开始为新的列名area拼凑字符串
            { $toString: { $multiply: [ "$size.h", "$size.w" ] } },#toString函数表示将size文档中的h和size文档中的w转换为字符串
            " ",#逗号隔开拼凑的字段串
            "$size.uom"#输出size的uom的值
         ]
      },
      reportNumber: { $literal: 1 }#新的字段reportNumber,$literal的作用主要用于$后面的值不会被解析,这里是添加一个新字段reportNumber返回一个值为1。
   }
)
...
{ "item" : "journal", "status" : "Available", "area" : "294 cm", "reportNumber" : 1 }
{ "item" : "notebook", "status" : "Available", "area" : "93.5 in", "reportNumber" : 1 }
{ "item" : "paper", "status" : "Discontinued", "area" : "93.5 in", "reportNumber" : 1 }
{ "item" : "planner", "status" : "Discontinued", "area" : "685.5 cm", "reportNumber" : 1 }
{ "item" : "postcard", "status" : "Available", "area" : "152.5 cm", "reportNumber" : 1 }

小知识:想要查看更多聚合表达式相关的内容可以去官方的这个链接:https://www.mongodb.com/zh-cn/docs/v5.0/reference/aggregation-quick-reference/#std-label-aggregation-expressions

find查询null值或缺失字段

1.清理之前的数据,新插入一些测试数据

MongoDB Enterprise test:PRIMARY> db.inventory.remove({})
MongoDB Enterprise test:PRIMARY> db.inventory.insertMany([
   { _id: 1, item: null },
   { _id: 2 }
])

2.查询null值,通过null进行匹配

###所有的数据都会被查到,缺失字段也会被纳为null
MongoDB Enterprise test:PRIMARY> db.inventory.find( { item: null } )
{ "_id" : 1, "item" : null }
{ "_id" : 2 }

3.查询不等于null的值

###无法获取到任何数据
MongoDB Enterprise test:PRIMARY> db.inventory.find( { item: { $ne : null } } )

4.使用type函数按照类型号查询,null的BSON类型号为10

MongoDB Enterprise test:PRIMARY> db.inventory.find( { item : { $type: 10 } } )
{ "_id" : 1, "item" : null }

小知识:更多类型号请查看官方链接:https://www.mongodb.com/zh-cn/docs/v5.0/reference/bson-types/

5.检查字段是否存在

###下方一个是null一个字段缺失,flase表示item字段不存在得有哪些,true表示存在得有哪些
MongoDB Enterprise test:PRIMARY> db.inventory.find( { item : { $exists: false } } )
{ "_id" : 2 }
MongoDB Enterprise test:PRIMARY> db.inventory.find( { item : { $exists: true } } )
{ "_id" : 1, "item" : null }

MongoDB之update更新

update更新语句可分为以下几类:

  • updateOne:即使匹配了多行的数据,最多也只更新匹配的1行数据
  • updateMany:更新所有匹配的行
  • replaceOne:即使匹配了多行的数据,最多也只会替换匹配的一行数据

updateOne

1.清理之前得测试数据,新插入一些数据

MongoDB Enterprise test:PRIMARY> db.inventory.remove({})
MongoDB Enterprise test:PRIMARY> db.inventory.insertMany( [
   { item: "canvas", qty: 100, size: { h: 28, w: 35.5, uom: "cm" }, status: "A" },
   { item: "journal", qty: 25, size: { h: 14, w: 21, uom: "cm" }, status: "A" },
   { item: "mat", qty: 85, size: { h: 27.9, w: 35.5, uom: "cm" }, status: "A" },
   { item: "mousepad", qty: 25, size: { h: 19, w: 22.85, uom: "cm" }, status: "P" },
   { item: "notebook", qty: 50, size: { h: 8.5, w: 11, uom: "in" }, status: "P" },
   { item: "paper", qty: 100, size: { h: 8.5, w: 11, uom: "in" }, status: "D" },
   { item: "planner", qty: 75, size: { h: 22.85, w: 30, uom: "cm" }, status: "D" },
   { item: "postcard", qty: 45, size: { h: 10, w: 15.25, uom: "cm" }, status: "A" },
   { item: "sketchbook", qty: 80, size: { h: 14, w: 21, uom: "cm" }, status: "A" },
   { item: "sketch pad", qty: 95, size: { h: 22.85, w: 30.5, uom: "cm" }, status: "A" }
] );

2.执行更新操作,更新得函数为 $set,$currentDate为将 lastModified 字段的值更新为当前日期。如果 lastModified 字段不存在,则 $currentDate 将创建该字段

###将qty为100得数据,修改为666并且status修改为X,并且将lastModified修改为最新得时间
MongoDB Enterprise test:PRIMARY> db.inventory.updateOne(
   { qty: 100 },
   {
     $set: { "qty": 666, status: "X" },
     $currentDate: { lastModified: true }
   }
)
###查询变更后的数据发现,qty为100得有两个,只修改了一个。这就是updateOne,并且也添加了一个lastModified字段
MongoDB Enterprise test:PRIMARY> db.inventory.find( { } )
{ "_id" : ObjectId("66d6b661b7601ddd4ded9540"), "item" : "canvas", "qty" : 666, "size" : { "h" : 28, "w" : 35.5, "uom" : "cm" }, "status" : "X", "lastModified" : ISODate("2024-09-03T07:16:41.552Z") }
{ "_id" : ObjectId("66d6b661b7601ddd4ded9545"), "item" : "paper", "qty" : 100, "size" : { "h" : 8.5, "w" : 11, "uom" : "in" }, "status" : "D" }
...

updateMany

1.将所有status为A得数据,全部更新为X

MongoDB Enterprise test:PRIMARY> db.inventory.updateMany(
   { status: "A" },
   {
     $set: { "status": "X" },
     $currentDate: { lastModified: true }
   }
)
###查询更新后得数据
MongoDB Enterprise test:PRIMARY> db.inventory.find( { },{status:1} )
...
{ "_id" : ObjectId("66d6b661b7601ddd4ded9540"), "status" : "X" }
{ "_id" : ObjectId("66d6b661b7601ddd4ded9541"), "status" : "X" }
{ "_id" : ObjectId("66d6b661b7601ddd4ded9542"), "status" : "X" }
...

2.更新嵌套文档中得数据

###将status为X得所有数据,嵌套文档size中得h得值全部更新为666,并修改lastModified得值为当前时间
MongoDB Enterprise test:PRIMARY> db.inventory.updateMany(
   { status: "X" },
   {
     $set: { "size.h": 666 },
     $currentDate: { lastModified: true }
   }
)
###查询更新后的数据
MongoDB Enterprise test:PRIMARY> db.inventory.find( { },{status:1,"size.h":1,lastModified:1} )
...
{ "_id" : ObjectId("66d6b661b7601ddd4ded9540"), "size" : { "h" : 666 }, "status" : "X", "lastModified" : ISODate("2024-09-03T07:26:35.749Z") }
{ "_id" : ObjectId("66d6b661b7601ddd4ded9541"), "size" : { "h" : 666 }, "status" : "X", "lastModified" : ISODate("2024-09-03T07:26:35.749Z") }
...

replaceOne

  • 替换文档时,替换文档必须仅包含字段/值对。替换文档不能包含更新操作符表达式。
  • 替换文档可以具有与原始文档不同的字段。在替换文档中,您可以省略_id字段,因为_id字段不可变。但是,如果您确实包含_id字段,则它的值必须与当前值相同。
###将qty为666得数据行,替换成string,888
MongoDB Enterprise test:PRIMARY> db.inventory.replaceOne(
{ qty: 666 },
{ string: "888"}
)
###查看数据可以发现,我们一整行数据变成了一个字段了就。这就是替换,与更新不同他是相当于重写整个数据行。而写入得值就是你匹配条件后面得值。
MongoDB Enterprise test:PRIMARY> db.inventory.find( { })
...
{ "_id" : ObjectId("66d6b661b7601ddd4ded9540"), "string" : "888" }
{ "_id" : ObjectId("66d6b661b7601ddd4ded9541"), "item" : "journal", "qty" : 25, "size" : { "h" : 666, "w" : 21, "uom" : "cm" }, "status" : "X", "lastModified" : ISODate("2024-09-03T07:26:35.749Z") }
...

通过聚合表达式更新数据

1.通过$replaceRoot 和 $mergeObjects函数修改集合默认值

###插入一个新数据
MongoDB Enterprise test:PRIMARY> db.students2.insertMany( [
   { "_id" : 1, quiz1: 8, test2: 100, quiz2: 9, modified: new Date("03/09/2023") },
   { "_id" : 2, quiz2: 5, test1: 80, test2: 89, modified: new Date("03/09/2023") },
] )
###验证数据,可以看到,id为1和id为2的数据行,分别缺少test1和quiz1字段。
MongoDB Enterprise test:PRIMARY> db.students2.find({})
{ "_id" : 1, "quiz1" : 8, "test2" : 100, "quiz2" : 9, "modified" : ISODate("2023-03-08T16:00:00Z") }
{ "_id" : 2, "quiz2" : 5, "test1" : 80, "test2" : 89, "modified" : ISODate("2023-03-08T16:00:00Z") }
###通过集合默认值,显示出test1和quiz1
MongoDB Enterprise test:PRIMARY> db.students2.updateMany( {},
  [
    { $replaceRoot: { newRoot:
       { $mergeObjects: [ { quiz1: 0, quiz2: 0, test1: 0, test2: 0 }, "$$ROOT" ] }
    } },
    { $set: { modified: "$$NOW"}  }
  ]
)
###查询数据
MongoDB Enterprise test:PRIMARY> db.students2.find({})
{ "_id" : 1, "quiz1" : 8, "quiz2" : 9, "test1" : 0, "test2" : 100, "modified" : ISODate("2024-09-03T08:51:03.835Z") }
{ "_id" : 2, "quiz1" : 0, "quiz2" : 5, "test1" : 80, "test2" : 89, "modified" : ISODate("2024-09-03T08:51:03.835Z") }
  • 通过replaceRoot和mergeObjects设置四个字段的默认值。
  • $$ROOT表示重构文档结构,可以在聚合管道中的某个阶段将当前文档的所有字段作为一个子文档重新组合,从而改变文档的结构。
  • $set部分,设置modified字段为$$NOW,NOW表示为当前时间。

2.使用聚合表达式avg和trunc,来更新文档。

###插入测试数据
MongoDB Enterprise test:PRIMARY> db.students3.insertMany( [
   { "_id" : 1, "tests" : [ 95, 92, 90 ], "modified" : ISODate("2019-01-01T00:00:00Z") },
   { "_id" : 2, "tests" : [ 94, 88, 90 ], "modified" : ISODate("2019-01-01T00:00:00Z") },
   { "_id" : 3, "tests" : [ 70, 75, 82 ], "modified" : ISODate("2019-01-01T00:00:00Z") }
] );
###通过函数计算每个id的平均分数,并进行重新写入。并根据分数输出结果为。
MongoDB Enterprise test:PRIMARY> db.students3.updateMany(
   { },
   [
     { $set: { average : { $trunc: [ { $avg: "$tests" }, 0 ] }, modified: "$$NOW" } },
     { $set: { grade: { $switch: {
                           branches: [
                               { case: { $gte: [ "$average", 90 ] }, then: "A" },
                               { case: { $gte: [ "$average", 80 ] }, then: "B" },
                               { case: { $gte: [ "$average", 70 ] }, then: "C" },
                               { case: { $gte: [ "$average", 60 ] }, then: "D" }
                           ],
                           default: "F"
     } } } }
   ]
)
###查询数据可以发现,根据已有的字段,计算出新的值并添加新的字段average和grade,并更新了时间。
MongoDB Enterprise test:PRIMARY> db.students3.find({})
{ "_id" : 1, "tests" : [ 95, 92, 90 ], "modified" : ISODate("2024-09-03T08:59:20.751Z"), "average" : 92, "grade" : "A" }
{ "_id" : 2, "tests" : [ 94, 88, 90 ], "modified" : ISODate("2024-09-03T08:59:20.751Z"), "average" : 90, "grade" : "A" }
{ "_id" : 3, "tests" : [ 70, 75, 82 ], "modified" : ISODate("2024-09-03T08:59:20.751Z"), "average" : 75, "grade" : "C" }
  • 第一个set时,更新字段average没有则添加这个字段,他的值来源于avg函数计算tests字段的平均值,并通过trunc函数取整数,其中的0表示忽略小数点后的所有数。再更新了modified字段为当前时间。
  • 第二个set时,更新字段grade,没有这个字段则添加,随后使用到了switch的case判断,判断上方新建的字段average,average大于等于90则为A,大于等于80则为B…最后的默认值为F,则不满足所有case的条件都为F。

3.通过$addFields 和map函数来更新字段。

###插入测试数据
MongoDB Enterprise test:PRIMARY> db.temperatures.insertMany( [
  { "_id" : 1, "date" : ISODate("2019-06-23"), "tempsC" : [ 4, 12, 17 ] },
  { "_id" : 2, "date" : ISODate("2019-07-07"), "tempsC" : [ 14, 24, 11 ] },
  { "_id" : 3, "date" : ISODate("2019-10-30"), "tempsC" : [ 18, 6, 8 ] }
] )
###更新数据将摄氏度温度,添加个字段更新为华氏度温度。
MongoDB Enterprise test:PRIMARY> db.temperatures.updateMany( { },
  [
    { $addFields: { "tempsF": {
          $map: {
             input: "$tempsC",
             as: "celsius",
             in: { $add: [ { $multiply: ["$$celsius", 9/5 ] }, 32 ] }
          }
    } } }
  ]
)
###查询数据
MongoDB Enterprise test:PRIMARY> db.temperatures.find()
{ "_id" : 1, "date" : ISODate("2019-06-23T00:00:00Z"), "tempsC" : [ 4, 12, 17 ], "tempsF" : [ 39.2, 53.6, 62.6 ] }
{ "_id" : 2, "date" : ISODate("2019-07-07T00:00:00Z"), "tempsC" : [ 14, 24, 11 ], "tempsF" : [ 57.2, 75.2, 51.8 ] }
{ "_id" : 3, "date" : ISODate("2019-10-30T00:00:00Z"), "tempsC" : [ 18, 6, 8 ], "tempsF" : [ 64.4, 42.8, 46.4 ] }

小知识:华氏度温度==(等于)32+ 摄氏度× 1.8

  • 上方的update:通过addFields函数添加一个为tempsF的字段,通过map函数进行映射数据。input为输入的数据tempsC字段。as为自定义的变量celsius,in为需要如何处理输入的数据,通过add函数将celsius的值加上32,再通过multiply乘以9分之5,9分之5等于1.8。

4.通过let变量进行更新操作

  • let变量是在5.0版本后新加入的功能,主要是调用和修改在命令中其他位置定义的变量。这里需要使用mongoshell客户端登录,才能解析let变量。使用mongo客户端无法进行解析会执行报错。
###添加测试数据
Enterprise test [direct: primary] db.cakeFlavors.insertMany( [
   { _id: 1, flavor: "chocolate" },
   { _id: 2, flavor: "strawberry" },
   { _id: 3, flavor: "cherry" }
] )
###将cherry修改为,orange
Enterprise test [direct: primary] mongodb_test> db.cakeFlavors.updateOne(
   {
      $expr: { $eq: [ "$flavor", "$$targetFlavor" ] }
   },
   [
      {
         $set: { flavor: "$$newFlavor" }
      }
   ],
   {
      let: { targetFlavor: "cherry", newFlavor: "orange" }
   }
)
###查询数据
Enterprise test [direct: primary] mongodb_test> db.cakeFlavors.find()
[
  { _id: 1, flavor: 'chocolate' },
  { _id: 2, flavor: 'strawberry' },
  { _id: 3, flavor: 'orange' }
]

mongoshell官方安装下载地址:https://www.mongodb.com/try/download/shell

  • 第一行使用expr匹配相关的值,表示调用变量targetFlavor,他的值为cherry,在let中声明了,-eq表示相等,也就是说当查询匹配时,flavor字段相等于cherry,就表示查到了,随后set时,修改flavor字段的值为newFlavor,此时调用let的变量newFlavor,值就是orange,修改完成。

MongoDB之delete删除

MongoDB删除文档的方式大致分为以下两种:

  • deleteOne:删除一条数据,不管匹配到了多少行,只删除一行。
  • deleteMany:删除所有匹配的数据

deleteOne

###清理之前的测试数据,新插入一批数据
Enterprise test [direct: primary] mongodb_test> db.inventory.remove({});
Enterprise test [direct: primary] db.inventory.insertMany( [
   { item: "journal", qty: 25, size: { h: 14, w: 21, uom: "cm" }, status: "A" },
   { item: "notebook", qty: 50, size: { h: 8.5, w: 11, uom: "in" }, status: "P" },
   { item: "paper", qty: 100, size: { h: 8.5, w: 11, uom: "in" }, status: "D" },
   { item: "planner", qty: 75, size: { h: 22.85, w: 30, uom: "cm" }, status: "D" },
   { item: "postcard", qty: 45, size: { h: 10, w: 15.25, uom: "cm" }, status: "A" },
] );
###清理掉一条item为journal的数据
Enterprise test [direct: primary] mongodb_test> db.inventory.deleteOne({item:"journal"})
###验证数据
Enterprise test [direct: primary] mongodb_test> db.inventory.find({});

deleteMany

###清理掉嵌套文档中h为8.5的数据
Enterprise test [direct: primary] mongodb_test> db.inventory.deleteMany({"size.h":8.5})
###清理掉表中的所有数据,不加任何条件就是全部删除。
Enterprise test [direct: primary] mongodb_test> db.inventory.deleteMany({})
###查询数据
Enterprise test [direct: primary] mongodb_test> db.inventory.find({});
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值