设为首页 收藏本站
查看: 912|回复: 0

[经验分享] mongodb指南(翻译)(四)

[复制链接]

尚未签到

发表于 2015-7-8 07:29:51 | 显示全部楼层 |阅读模式
  运行mongodb
  请参与快速启动指南来启动mongodb。
  
  连接到数据库
  首先使用数据库shell程序来操作数据库。(我们同样可以使用任何语言的驱动来做类似的操作。shell程序可以很方便的进行交互和管理。)
  这样启动mongodb JavaScript shell:



view plain

  • # 'mongo' is shell binary. exact location might vary depending on  
  • # installation method and platform  
  • $ bin/mongo  
  
默认情况下shell程序会连接到本地的数据库“test”。你将看到:



view plain

  • MongoDB shell version:   
  • url: test  
  • connecting to: test  
  • type "help" for help  
  • >  
  
"connecting to:"告诉你目前正在使用的数据库名称。可以这样切换数据库:



view plain

  • > use mydb  
  • switched to db mydb  
  
切换数据库的use命令并不会立即创建这个数据库-数据库延迟到数据第一次插入的时候创建。这意味着如果你use某个数据库,但是show dbs命令并不会将它列出来除非有数据插入。
  要想查看可以使用的命令列表,可以敲入help.
  
  动态模式(模式自由)
  MongoDB像传统的RDBMS一样拥有数据库、集合和索引。在一些场合(数据库和集合)这些对象可以被隐式创建,不过一旦创建它们就存在于一个系统目录中(db.systems.collections, db.system.indexes)。
  集合中包含了(BSON)文档。在这些文档中是一些域。在mongodb中没有预定义的域(对应于RDBMS中的列)。对于文档内的域没有任何模式 要求-这些域和他们的值类型可以是任何类型。在这里增加一列也没有“alter table”的概念。尽管没有这样一个要求,但实际应用中,在一个集合中的文档拥有相类似的结构是非常普遍的。这种灵活性意味着模式迁移和增大在实际中非 常容易-很少会需要你去写脚本做类似于“alter table”的操作。除了让模式迁移灵活外,这种便利使得在数据库之上做迭代开发更加容易。
  
  向集合中插入数据
  我们首先创建一个集合然后向里面插入一些数据。我们会创建两个对象,j和t,然后将他们保存在集合thins中。
  在接下来的例子中,">"代表shell中输入命令的提示符。



view plain

  • > j = { name : "mongo" };  
  • {"name" : "mongo"}  
  • > t = { x : 3 };  
  • { "x" : 3 }  
  • > db.things.save(j);  
  • > db.things.save(t);  
  • > db.things.find();  
  • { "_id" : ObjectId("4c2209f9f3924d31102bd84a"), "name" : "mongo" }  
  • { "_id" : ObjectId("4c2209fef3924d31102bd84b"), "x" : 3 }  
  • >  
  
有几点需要注明:

  • 我们没有预先创建这个集合。在我们首次插入数据时数据库自动创建了它。
  • 保存的文档可以拥有不同的结构-实际上在这个例子中,这两个文档根本没有任何相同的数据元素。在实际应用中,在一个集合中保存的数据通常具有相同的结构。
  • 在插入到数据库之前,对象的域_id被赋予了一个object ID(如果还没有这个域).
  • 当你运行上面的例子时,你的ObjectID值可能会不同。
  让我们增加更多的记录到该集合中:



view plain

  • > for (var i = 1; i  db.things.find();  
  • { "_id" : ObjectId("4c2209f9f3924d31102bd84a"), "name" : "mongo" }  
  • { "_id" : ObjectId("4c2209fef3924d31102bd84b"), "x" : 3 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd856"), "x" : 4, "j" : 1 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd857"), "x" : 4, "j" : 2 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd858"), "x" : 4, "j" : 3 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd859"), "x" : 4, "j" : 4 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd85a"), "x" : 4, "j" : 5 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd85b"), "x" : 4, "j" : 6 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd85c"), "x" : 4, "j" : 7 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd85d"), "x" : 4, "j" : 8 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd85e"), "x" : 4, "j" : 9 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd85f"), "x" : 4, "j" : 10 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd860"), "x" : 4, "j" : 11 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd861"), "x" : 4, "j" : 12 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd862"), "x" : 4, "j" : 13 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd863"), "x" : 4, "j" : 14 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd864"), "x" : 4, "j" : 15 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd865"), "x" : 4, "j" : 16 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd866"), "x" : 4, "j" : 17 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd867"), "x" : 4, "j" : 18 }  
  • has more  
  
注意并不是所有的文档都会显示出来-当自动迭代一个游标时,shell将返回数目限制在20.由于我们已经在集合中插入了2个文档,因此我们只看到了18个新插入的文档。
  
  如果我们想要返回下一组结果,可以使用快捷方式it。接着上面的代码:



view plain

  • { "_id" : ObjectId("4c220a42f3924d31102bd866"), "x" : 4, "j" : 17 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd867"), "x" : 4, "j" : 18 }  
  • has more  
  • > it  
  • { "_id" : ObjectId("4c220a42f3924d31102bd868"), "x" : 4, "j" : 19 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd869"), "x" : 4, "j" : 20 }  
  
技术上,find()返回一个游标对象。但在上面的实例中,我们并没有将这个游标赋值到一个变量。因此,shell自动迭代了这个游标,返回一组初始的结果,并允许我们使用it命令继续迭代。
  但是我们还可以直接使用cursor;在下面的章节中会讨论该怎么做。
  
  从查询中获取数据
  前面我们讨论了任何深度的查询,接下来我们讲讲如果使用查询结果工作-一个游标对象。我们将使用简单的find()查询函数,它会返回集合中的任何内容,后面会讲如果创建特殊的查询。
  为了使用mongo shell来查看集合中的所有元素,我们需要显式的使用find()操作返回的游标。
  让我们再做一次相同的查询,但是这次使用find()返回的游标,然后在while循环中迭代它:



view plain

  • > var cursor = db.things.find();  
  • > while (cursor.hasNext()) printjson(cursor.next());  
  • { "_id" : ObjectId("4c2209f9f3924d31102bd84a"), "name" : "mongo" }  
  • { "_id" : ObjectId("4c2209fef3924d31102bd84b"), "x" : 3 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd856"), "x" : 4, "j" : 1 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd857"), "x" : 4, "j" : 2 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd858"), "x" : 4, "j" : 3 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd859"), "x" : 4, "j" : 4 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd85a"), "x" : 4, "j" : 5 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd85b"), "x" : 4, "j" : 6 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd85c"), "x" : 4, "j" : 7 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd85d"), "x" : 4, "j" : 8 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd85e"), "x" : 4, "j" : 9 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd85f"), "x" : 4, "j" : 10 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd860"), "x" : 4, "j" : 11 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd861"), "x" : 4, "j" : 12 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd862"), "x" : 4, "j" : 13 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd863"), "x" : 4, "j" : 14 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd864"), "x" : 4, "j" : 15 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd865"), "x" : 4, "j" : 16 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd866"), "x" : 4, "j" : 17 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd867"), "x" : 4, "j" : 18 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd868"), "x" : 4, "j" : 19 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd869"), "x" : 4, "j" : 20 }  
  
上面的例子显示了游标风格的迭代。hasNext()函数告诉我们是否还有文档可以返回,next()函数则返回下一个文档。我们还使用了内置的printjson()方法将文档翻译为漂亮的JSON风格的格式。
  当在JavaScript shell下面工作,我们还可以使用该语言实用的基本组件,然后对游标调用forEach。重复上面的例子,但是对游标不再使用while循环,而是直接使用forEach():



view plain

  • > db.things.find().forEach(printjson);  
  • { "_id" : ObjectId("4c2209f9f3924d31102bd84a"), "name" : "mongo" }  
  • { "_id" : ObjectId("4c2209fef3924d31102bd84b"), "x" : 3 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd856"), "x" : 4, "j" : 1 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd857"), "x" : 4, "j" : 2 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd858"), "x" : 4, "j" : 3 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd859"), "x" : 4, "j" : 4 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd85a"), "x" : 4, "j" : 5 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd85b"), "x" : 4, "j" : 6 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd85c"), "x" : 4, "j" : 7 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd85d"), "x" : 4, "j" : 8 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd85e"), "x" : 4, "j" : 9 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd85f"), "x" : 4, "j" : 10 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd860"), "x" : 4, "j" : 11 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd861"), "x" : 4, "j" : 12 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd862"), "x" : 4, "j" : 13 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd863"), "x" : 4, "j" : 14 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd864"), "x" : 4, "j" : 15 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd865"), "x" : 4, "j" : 16 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd866"), "x" : 4, "j" : 17 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd867"), "x" : 4, "j" : 18 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd868"), "x" : 4, "j" : 19 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd869"), "x" : 4, "j" : 20 }  
  
在forEach()的实例中,我们必须为游标定义一个函数,对于每一个文档它都会被调用。
  在mongo shell,你处理游标还可以像处理数组:



view plain

  • > var cursor = db.things.find();  
  • > printjson(cursor[4]);  
  • { "_id" : ObjectId("4c220a42f3924d31102bd858"), "x" : 4, "j" : 3 }  
  
当以这种方式使用游标时,注意所有的值直到访问的最大值(上面是cursor[4])都会被同时装载到RAM中。这对于很大的结果集是不合适的,因为你会耗尽内存。对于任何返回大量元素的查询,游标应当作为迭代器来使用。
  除了以数组风格来访问游标,你可以将游标转换为一个真正的数组:



view plain

  • > var arr = db.things.find().toArray();  
  • > arr[5];  
  • { "_id" : ObjectId("4c220a42f3924d31102bd859"), "x" : 4, "j" : 4 }  
  
请注意这种数组特性仅适用于mongo-交互型shell,并不是所有的驱动都提供这种功能。
  mongodb游标不是快照-在你第一次和最后一次调用next()中间,游标可能返回或者不返回你或者其他用户在这个集合中所执行的操作。使用显式的锁动作来执行一个快照型的查询。
  
  指定查询的返回值
  现在我们已经知道了如果使用查询返回的游标工作,让我们关注怎么定制查询去返回特定的内容。
  通常的方法就是创建"查询文档",这个查询文档指出了需要匹配的键和值的样式。
  相比于解释,这些更容易演示。在接下来的例子中,我们会给出SQL查询例子,然后演示如何通过mongo shell来表达相同的查询。这种指定查询的方法在mongodb中是很基础的,所以你将能在所有的驱动或者语言中找到相同的通用的功能。



view plain

  • SELECT * FROM things WHERE name="mongo"  



view plain

  • > db.things.find({name:"mongo"}).forEach(printjson);  
  • { "_id" : ObjectId("4c2209f9f3924d31102bd84a"), "name" : "mongo" }  



view plain

  • SELECT * FROM things WHERE x=4  



view plain

  • > db.things.find({x:4}).forEach(printjson);  
  • { "_id" : ObjectId("4c220a42f3924d31102bd856"), "x" : 4, "j" : 1 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd857"), "x" : 4, "j" : 2 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd858"), "x" : 4, "j" : 3 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd859"), "x" : 4, "j" : 4 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd85a"), "x" : 4, "j" : 5 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd85b"), "x" : 4, "j" : 6 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd85c"), "x" : 4, "j" : 7 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd85d"), "x" : 4, "j" : 8 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd85e"), "x" : 4, "j" : 9 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd85f"), "x" : 4, "j" : 10 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd860"), "x" : 4, "j" : 11 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd861"), "x" : 4, "j" : 12 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd862"), "x" : 4, "j" : 13 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd863"), "x" : 4, "j" : 14 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd864"), "x" : 4, "j" : 15 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd865"), "x" : 4, "j" : 16 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd866"), "x" : 4, "j" : 17 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd867"), "x" : 4, "j" : 18 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd868"), "x" : 4, "j" : 19 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd869"), "x" : 4, "j" : 20 }  
  
  查询表达式就是文档本身。形如{a:A,b:B,...}的查询文档意思是"where a--A and b==B and...".更多关于查询能力的信息可以参阅查询和游标。
  MongoDB还允许只返回"部分文档"-这些文档仅包含数据库中文档元素的一个子集。
  实现这个功能,你在find()查询函数中增加第二个参数,提供一个需要返回元素列表的文档就可以了。
  为了演示这个功能,我们使用增加一个限制仅返回”j“元素的参数来重复上一个find({x:4})的例子:



view plain

  • SELECT j FROM things WHERE x=4  



view plain

  • > db.things.find({x:4}, {j:true}).forEach(printjson);  
  • { "_id" : ObjectId("4c220a42f3924d31102bd856"), "j" : 1 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd857"), "j" : 2 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd858"), "j" : 3 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd859"), "j" : 4 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd85a"), "j" : 5 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd85b"), "j" : 6 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd85c"), "j" : 7 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd85d"), "j" : 8 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd85e"), "j" : 9 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd85f"), "j" : 10 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd860"), "j" : 11 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd861"), "j" : 12 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd862"), "j" : 13 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd863"), "j" : 14 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd864"), "j" : 15 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd865"), "j" : 16 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd866"), "j" : 17 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd867"), "j" : 18 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd868"), "j" : 19 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd869"), "j" : 20 }  
  
注:默认情况下"_id"域始终会返回。
  
  findOne()-语法便利
  简便起见,mongo shell(和其他的驱动)允许通过findOne()函数仅返回一个文档,避免了程序从头开始处理游标。findOne()接受与find()方法相同 的参数,但是不再返回游标,而是返回要么数据库中第一个符合的文档,要么返回null如果没有匹配到。
  作为例子,我们检索一个符合"name=="mongo""的文档。除了对游标调用next()(当然首先判断是否为空)或者将游标当做数组处理读取0th元素,还有很多方法可以使用、
  无论如何,findOne()方法方便并且高效:



view plain

  • > printjson(db.things.findOne({name:"mongo"}));  
  • { "_id" : ObjectId("4c2209f9f3924d31102bd84a"), "name" : "mongo" }  
  
这个方法更加高效,是因为客户端向数据库请求单个对象,这样数据库和网络和以前相比只做少量的工作。它等效于find({name:"mogno"}).limit(1).
  另外一个使用_id查询单个文档的例子:



view plain

  • > var doc = db.things.findOne({_id:ObjectId("4c2209f9f3924d31102bd84a")});  
  • > doc  
  • { "_id" : ObjectId("4c2209f9f3924d31102bd84a"), "name" : "mongo" }  
  
  使用limit()限制返回个数
  你可以通过limit()函数来设定返回结果的最大个数,从而限定了查询结果的数据大小。
  由于性能的原因它是强烈推荐使用的,这样就限定了数据库需要做的工作,限定了需要通过网络返回的数据量大小。例如:



view plain

  • > db.things.find().limit(3);  
  • { "_id" : ObjectId("4c2209f9f3924d31102bd84a"), "name" : "mongo" }  
  • { "_id" : ObjectId("4c2209fef3924d31102bd84b"), "x" : 3 }  
  • { "_id" : ObjectId("4c220a42f3924d31102bd856"), "x" : 4, "j" : 1 }  
  更多帮助
  除了使用"help"命令,你还可以在db和db.whatever上面调用help去查看可用的方法。
  如果你很好奇某个函数内部在做什么,你可以输入函数名(不要())shell会打印出源代码,例如:



view plain

  • > printjson  
  • function (x) {  
  • print(tojson(x));  
  • }  
  
mongo是一个完全的JavaScript shell,因此任何JavaScript函数,语法,或者类都可以在该shell中使用。另外,mongodb也定义了一些自己的类和全局变量(如db). 你可以http://api.mongodb.org/js/在查看完整的API.
  
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-84230-1-1.html 上篇帖子: MongoDB学习(1)—在Windows系统中安装MongoDB 下篇帖子: MongoDB分片中片键的选择
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表