MongoDB实战第二版笔记(3)第二章笔记

备注:以下的“结果”默认情况是输出结果。

  1、启动shell输入指令 mongo即可。

  运行后如下所示就是成功。

MongoDB实战第二版笔记(3)第二章笔记

  2、类似RDBMS的表,MongoDB称之为集合。用于对不同类型文档进行分类。

  3、为什么MongoDB有数据库和集合?取决于MongoDB如何在磁盘上写数据。

  4、使用数据库代码

use tutorial

  5、MongoDB只有第一次插入数据库和集合才会创建,符合其动态操作数据的模式。单个数据库和集合也可以在运行时创建。

  6、创建一个文档的示例

{username:"smith"}

  结果:

smith

  7、插入示例:选择目标(user)集合插入

db.users.insert({username:"smith"})

  结果:

WriteResult({ "nInserted" : 1 })

  会有延迟,原因在于要在磁盘创建tutorial数据库而且创建users集合,分配二者初始化文件。

  8、查询示例:查看之前弄的users集合。例子等价于 db.users.find({})

 db.users.find()

  结果:

{ "_id" : ObjectId("5bec04af9c151e74b547bf82"), "username" : "smith" }

  9、MongoDB文档都需要_id,如果创建时没有该字段会专门创建一个MongoDB ObjectID添加到文档。

后面继续按照上面添加一个文档用户。

  10、有两个文档可以用如下命令查看文档数量

db.users.count()

  11、简单条件查询示例:

 db.users.find({username:"jones"})

  结果:

{ "_id" : ObjectId("5bec06c39c151e74b547bf83"), "username" : "jones" }

  12、多字段查询示例(隐含创建AND语句)【三点是MongoDB shell自动添加】

db.users.find({
... _id:ObjectId("5bec04af9c151e74b547bf82"),
... username:"smith"
... })

  结果:

{ "_id" : ObjectId("5bec04af9c151e74b547bf82"), "username" : "smith" }
  • 条件会使用AND按照并且关系进行查询,索引必须匹配_id和username字段。

  • 可以使用$and操作符达到该效果

    db.users.find({ $and:[
    ... {_id:ObjectId("5bec04af9c151e74b547bf82")},
    ... {username:"smith"}
    ... ]})
    

   结果:

{ "_id" : ObjectId("5bec04af9c151e74b547bf82"), "username" : "smith" }
  • OR查询类似,将$and替换$or

     db.users.find({ $or:[
    ... {username:"smith"},
    ... {username:"jones"}
    ... ]})
    

       结果:

    { "_id" : ObjectId("5bec04af9c151e74b547bf82"), "username" : "smith" }
    { "_id" : ObjectId("5bec06c39c151e74b547bf83"), "username" : "jones" }
    

       13、所有更新至少需要2个参数,第一个是指定要更新的文档,第二个是如何修改。

       14、默认update()只更新一个文档

       15、更新类型:

    (1)在一个文档或多个文档上修改;(需要传入文档参数和操作符参数)

       i)$set设置单个字段

db.users.update({username:"smith"},{$set:{country:"Canada"}})

  结果:

WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

      ii)$unset删除某字段

    (2)新文档代替旧文档

 db.users.update({username:"smith"},{country:"Canada"})

  结果

WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

第一个参数用来匹配,第二个参数用来更新。结果删除掉了username字段(查询字段)

  16、更新复杂元素

  采用$set更新,示例的间隔缩进非必须,但可避免错误,使得可读性增强。

> db.users.update({username:"smith"}, 
... {
...    $set:{
...        favorites:{
...            cities:["Chicago","Cheyenne"],
...            movies:["Casablanca","For a Few Dollars More","The Sting"]
...        }
...    }
... })

  结果:

WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

  17、加原点的查询。A.B是搜索键名为A的对象,其内部键为B的元素。

db.users.find({"favorites.movies":"Casablanca"})

  结果:

{ "_id" : ObjectId("5bec04af9c151e74b547bf82"), "username" : "smith", "favorites" : { "cities" : [ "Chicago", "Cheyenne" ], "movies" : [ "Casablanca", "For a Few Dollars More", "The Sting" ] } }
{ "_id" : ObjectId("5bec06c39c151e74b547bf83"), "username" : "jones", "favorites" : { "movies" : [ "Casablanca", "Rocky" ] } }

  18、高级更新,给列表添加元素,使用$push或$addToSet。第二个是唯一的,阻止重复。

  19、删除数据

  • 清空集合(不带参数),示例是清空foo集合所有文档内容。

    db.foo.remove(
  • 删除集合某个文档,remove()参数是查询选择器。类比SQL的DELETE命令。

    db.users.remove({"favorites.cities":"Cheyenne"})
    

   结果

WriteResult({ "nRemoved" : 1 })
  • 删除集合及附带索引数据,使用drop()方法,返还Boolean数据表明成功与否

    db.users.drop()
    

   20、shell的其他特性

  • 支持快捷键列表,如自动完成或列举完成的可能情况【Tab键】
  • 输入help得到更多shell信息

  21、类似JavaScript,用循环创建大集合。

for(i=0;i<20000;i++){
... db.numbers.save({num:i});
... }

  结果:

WriteResult({ "nInserted" : 1 })

  22、find()显示数量(不同shell不一样,博主的是显示20条),如果过多则分页显示。it命令来换下一次结果集。

  23、用$gt$lt运算符进行范围查询,分布表示大于和小于。还有$gte$lte分别是大于等于和小于等于,$ne表示不等于。

db.numbers.find({num:500})

  结果:

{ "_id" : ObjectId("5bef7c6d9c151e74b5480da0"), "num" : 19996 }
{ "_id" : ObjectId("5bef7c6d9c151e74b5480da1"), "num" : 19997 }
{ "_id" : ObjectId("5bef7c6d9c151e74b5480da2"), "num" : 19998 }
{ "_id" : ObjectId("5bef7c6d9c151e74b5480da3"), "num" : 19999 }

  设置上下限

db.numbers.find({num:{"$gt":20,"$lt":25}})

  结果:

{ "_id" : ObjectId("5bef7c629c151e74b547bf99"), "num" : 21 }
{ "_id" : ObjectId("5bef7c629c151e74b547bf9a"), "num" : 22 }
{ "_id" : ObjectId("5bef7c629c151e74b547bf9b"), "num" : 23 }
{ "_id" : ObjectId("5bef7c629c151e74b547bf9c"), "num" : 24 }

  24、查询计划:接收到查询后弄清如何执行查询。EXPLAIN描述查询路径并允许开发者通过确定查询使用的索引诊断慢的查询语句。

db.numbers.find({num:{"$gt":19995}}).explain("executionStats")

  结果:

{
	"queryPlanner" : {
		"plannerVersion" : 1,
		"namespace" : "tutorial.numbers",
		"indexFilterSet" : false,
		"parsedQuery" : {
			"num" : {
				"$gt" : 19995
			}
		},
		"winningPlan" : {
			"stage" : "COLLSCAN",
			"filter" : {
				"num" : {
					"$gt" : 19995
				}
			},
			"direction" : "forward"
		},
		"rejectedPlans" : [ ]
	},
	"executionStats" : {
		"executionSuccess" : true,
		"nReturned" : 4,
		"executionTimeMillis" : 7,
		"totalKeysExamined" : 0,
		"totalDocsExamined" : 20000,
		"executionStages" : {
			"stage" : "COLLSCAN",
			"filter" : {
				"num" : {
					"$gt" : 19995
				}
			},
			"nReturned" : 4,
			"executionTimeMillisEstimate" : 10,
			"works" : 20002,
			"advanced" : 4,
			"needTime" : 19997,
			"needFetch" : 0,
			"saveState" : 156,
			"restoreState" : 156,
			"isEOF" : 1,
			"invalidates" : 0,
			"direction" : "forward",
			"docsExamined" : 20000
		}
	},
	"serverInfo" : {
		"host" : "ubuntu",
		"port" : 27017,
		"version" : "3.0.6",
		"gitVersion" : "1ef45a23a4c5e3480ac919b28afcba3c615488f2"
	},
	"ok" : 1
}
  • totalKeysExamined字段显示整个扫描的索引数量,值为0。
  • docsExamined表示扫描集合数量,值20000。

  25、创建索引用createIndex()方法。MongoDB3保持2中可用的ensureIndex(),3中是其别名。示例展示为num键创建索引,值为1指将numbers集合的所有文档num键建立升序索引。【本质是确定索引的键】

db.numbers.createIndex({num:1})

  结果:

{
	"createdCollectionAutomatically" : false,
	"numIndexesBefore" : 1,
	"numIndexesAfter" : 2,
	"ok" : 1
}

  26、getIndexes()查看创建索引是否成功。

db.numbers.getIndexes()

  结果:

[
	{
		"v" : 1,
		"key" : {
			"_id" : 1
		},
		"name" : "_id_",
		"ns" : "tutorial.numbers"
	},
	{
		"v" : 1,
		"key" : {
			"num" : 1
		},
		"name" : "num_1",
		"ns" : "tutorial.numbers"
	}
]

  集合中有两个所有,一个是标准_id所有,自动为集合创建。第二个是前面定义的所有。没有设置名字则MongoDB会自动创建,如num_1。

  再次使用下面的命令,会发现只扫描四个文档,降低查询时间。

db.numbers.find({num:{"$gt":19995}}).explain("executionStats")

  27、索引需要成本,会占用空间,会提高插入成本。

  28、获取数据库信息

  • show dbs打印所有数据库列表信息

    > show dbs
    local     0.078GB
    tutorial  0.078GB
    
  • show collections展示当前数据库里所有集合。【一般用于复杂调试和优化】

    > show collections
    numbers
    system.indexes
    

  system.indexes是每个数据库都存在的特殊集合,它的每个入口都定义了数据库所有。MongoDB3放弃对其的访问,可使用createIndexes或listIndexes替换。getIndexes()可以被db.runCommand({“listIndexes”:“numbers”})替换。

  • stats()低级别数据库和集合分析,下面两个例子分布是数据库和集合上执行该命令。

    > db.stats()
    {
    	"db" : "tutorial",
    	"collections" : 3,
    	"objects" : 20006,
    	"avgObjSize" : 48.00959712086374,
    	"dataSize" : 960480,
    	"storageSize" : 2805760,
    	"numExtents" : 7,
    	"indexes" : 2,
    	"indexSize" : 1169168,
    	"fileSize" : 67108864,
    	"nsSizeMB" : 16,
    	"extentFreeList" : {
    		"num" : 0,
    		"totalSize" : 0
    	},
    	"dataFileVersion" : {
    		"major" : 4,
    		"minor" : 22
    	},
    	"ok" : 1
    }
    
    > db.numbers.stats()
    {
    	"ns" : "tutorial.numbers",
    	"count" : 20000,
    	"size" : 960064,
    	"avgObjSize" : 48,
    	"numExtents" : 5,
    	"storageSize" : 2793472,
    	"lastExtentSize" : 2097152,
    	"paddingFactor" : 1,
    	"paddingFactorNote" : "paddingFactor is unused and unmaintained in 3.0. It remains hard coded to 1.0 for compatibility only.",
    	"userFlags" : 1,
    	"capped" : false,
    	"nindexes" : 2,
    	"totalIndexSize" : 1169168,
    	"indexSizes" : {
    		"_id_" : 654080,
    		"num_1" : 515088
    	},
    	"ok" : 1
    }
    

  29、无论提供什么功能,所有数据库命令实现都在$cmd的虚拟集合上实现查询。

  • db.stats()等价于 db.runCommand({dbstats:1})

  • db.runCommand查看内部机制

    > db.runCommand
    function ( obj, extra ){
        if ( typeof( obj ) == "string" ){
            var n = {};
            n[obj] = 1;
            obj = n;
            if ( extra && typeof( extra ) == "object" ) {
                for ( var x in extra ) {
                    n[x] = extra[x];
                }
            }
        }
        return this.getCollection( "$cmd" ).findOne( obj );
    }
    
  • 数据库命令就是特殊集合$cmd上的查询。查询选择器定义了命令本身。

  30、db.help()查看通用数据库操作方法。

  31、输入任意方法的首字母,按Tab键两次就可看到所有匹配方法。

  32、要查看某函数如何实现,则不需要加括号,只需要输入方法名。

运用函数总结

操作 命令 参数
插入 insert() 文档JSON
查询 find() $and查询,$or查询。
{}默认空条件
其后使用pretty()附加操作可从服务器返回良好格式结构
如果结果集过多,分页显示,it命令让显示下一页结果。
$gt$lt运算符进行范围查询,分布表示大于和小于。还有
更新 update() 两个参数,第一个参数是文档参数,用于匹配
第二个参数可以是$set$unset对字段处理。
$addToSet$push可以给列表添加元素,后者是唯一的阻止重复数据。
第三个参数是boolean类型,表示是否允许upsert。当文档不存在时是否插入,取决于更新操作是操作符更新还是替换更新。
第四个参数是boolean类型,表示是否多个更新,默认是对第一个匹配文档更新。
删除 remove() 无参,则清空集合文档。
有参且是查询选择器,则删除在集合中查询出来的文档。
创建索引 createIndex() MongoDB3保持2中可用的ensureIndex(),3中是其别名。
查看创建索引是否成功 getIndexes()
打印所有数据库列表信息 show dbs
低级别数据库和集合分析 stats()
任意命令调用 runCommand() 传递不同参数可以调用等价命令。是对特殊集合$$$cmd的查询。
查看通用数据库操作方法 help()