前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >浅尝辄止MongoDB:操作(3)

浅尝辄止MongoDB:操作(3)

作者头像
用户1148526
发布2019-05-25 19:43:10
9310
发布2019-05-25 19:43:10
举报
文章被收录于专栏:Hadoop数据仓库Hadoop数据仓库

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://cloud.tencent.com/developer/article/1433175

目录

5. 批处理数据

6. 重命名集合

7. 删除数据

8. 引用数据库

9. 使用与索引相关的函数


代码语言:txt
复制
    大部分摘自《MongoDB大数据处理权威指南》(第3版)。 

5. 批处理数据

代码语言:txt
复制
    MongoDB允许批量执行写入操作。通过这种方式,可首先定义数据集,再一次性写入它们。批量写入操作只能处理单一集合,可用于插入、更新或删除数据。
代码语言:txt
复制
    在批量写入数据之前,首先需要告诉MongoDB如何写入数据:有序还是无序。以有序方式执行操作时,MongoDB会按顺序执行操作列表。如果在处理一个写入操作时发生错误,就不处理剩下的操作。使用无序写入操作时,MongoDB以并行方式执行操作。如果在处理一个写入操作时发生错误,MongoDB将继续处理剩余的写入操作。
代码语言:txt
复制
    按以下步骤执行批处理:
  1. 初始化操作列表,有序操作的初始化函数是db.collection.initializeorderedBulkOp(),无序操作的初始化函数是db.collection.initializeUnorderedBulkOp()。
  2. 将要执行的操作插入操作列表。
  3. 使用execute()命令执行操作。
  4. 使用getOperations()评估输出(可选)。
代码语言:txt
复制
    下面看MongoDB官方文档中的例子:
代码语言:javascript
复制
> var bulk = db.users.initializeOrderedBulkOp();
> bulk.insert( { user: "abc123", status: "A", points: 0 } );
> bulk.insert( { user: "ijk123", status: "A", points: 0 } );
> bulk.insert( { user: "mop123", status: "P", points: 0 } );
> bulk.find( { status: "D" } ).remove();
> bulk.find( { status: "P" } ).update( { $set: { comment: "Pending" } } );
> bulk.execute();
BulkWriteResult({
    "writeErrors" : [ ],
    "writeConcernErrors" : [ ],
    "nInserted" : 3,
    "nUpserted" : 0,
    "nMatched" : 1,
    "nModified" : 1,
    "nRemoved" : 0,
    "upserted" : [ ]
})
>
代码语言:txt
复制
    上面的批处理中顺序执行了3个插入、1个删除、1个更新操作。注意列表中最多可以包含1000个操作,超过此限制时,MongoDB会自动分割列表,把它们放在几个包含1000个操作的组中。执行后的数据如下:
代码语言:javascript
复制
> db.users.find();
{ "_id" : ObjectId("5bad83a52a4ee8fc88cee341"), "user" : "abc123", "status" : "A", "points" : 0 }
{ "_id" : ObjectId("5bad83a52a4ee8fc88cee342"), "user" : "ijk123", "status" : "A", "points" : 0 }
{ "_id" : ObjectId("5bad83a52a4ee8fc88cee343"), "user" : "mop123", "status" : "P", "points" : 0, "comment" : "Pending" }
>
代码语言:txt
复制
    一旦使用execute()命令执行了批操作,就能够审查执行的写入操作。可以评估是否成功写入了所有数据,以及按什么顺序写入的。此外,一旦在写入期间出现问题,输出也有助于了解所执行的操作。使用getOperations()命令执行审查:
代码语言:javascript
复制
> bulk.getOperations();
[
    {
        "originalZeroIndex" : 0,
        "batchType" : 1,
        "operations" : [
            {
                "_id" : ObjectId("5bad83a52a4ee8fc88cee341"),
                "user" : "abc123",
                "status" : "A",
                "points" : 0
            },
            {
                "_id" : ObjectId("5bad83a52a4ee8fc88cee342"),
                "user" : "ijk123",
                "status" : "A",
                "points" : 0
            },
            {
                "_id" : ObjectId("5bad83a52a4ee8fc88cee343"),
                "user" : "mop123",
                "status" : "P",
                "points" : 0
            }
        ]
    },
    {
        "originalZeroIndex" : 3,
        "batchType" : 3,
        "operations" : [
            {
                "q" : {
                    "status" : "D"
                },
                "limit" : 0
            }
        ]
    },
    {
        "originalZeroIndex" : 4,
        "batchType" : 2,
        "operations" : [
            {
                "q" : {
                    "status" : "P"
                },
                "u" : {
                    "$set" : {
                        "comment" : "Pending"
                    }
                },
                "multi" : true,
                "upsert" : false
            }
        ]
    }
]
>
代码语言:txt
复制
    返回的数组包含operations键下处理的所有数据,batchType键表示执行的操作类型,1、2、3分别表示insert、update、delete操作。在无序列表中处理各类操作时,MongoDB会将这些操作按类型(插入、更新、删除)分组来提高性能。因此,应确保应用不依赖操作的执行顺序。有序列表的操作只会组合相同类型的连续操作,所以它们仍是按顺序处理的。
代码语言:txt
复制
    在一次处理大量数据时,批处理操作是非常有用的,还不会影响事先可用的数据集。

6. 重命名集合

代码语言:javascript
复制
> show collections;
audit
audit100
media
products
users
> db.users.renameCollection("users1");
{ "ok" : 1 }
> show collections;
audit
audit100
media
products
users1
>
代码语言:txt
复制
    MongoDB没有提供直接的修改数据库名称的函数,但可以使用renameCollection()把一个数据库中所有的集合移动到新库下,就相当于把整个库重命名了。
代码语言:javascript
复制
> show dbs;
admin    0.000GB
config   0.000GB
library  0.000GB
local    0.000GB
> use admin
switched to db admin
> db.runCommand({renameCollection: "test.test", to: "test1.test"});
{
    "ok" : 0,
    "errmsg" : "source namespace does not exist",
    "code" : 26,
    "codeName" : "NamespaceNotFound"
}
> db.runCommand({renameCollection: "library.users1", to: "test.users1"});
{ "ok" : 1 }
> show dbs;
admin    0.000GB
config   0.000GB
library  0.000GB
local    0.000GB
test     0.000GB
> use test;
switched to db test
> show collections;
users1
> use library;
switched to db library
> show collections;
audit
audit100
media
products
>

7. 删除数据

代码语言:txt
复制
    deleteOne()删除匹配条件的一个文档:
代码语言:javascript
复制
> db.users1.find({"status" : "A"});
{ "_id" : ObjectId("5bad83a52a4ee8fc88cee341"), "user" : "abc123", "status" : "A", "points" : 0 }
{ "_id" : ObjectId("5bad83a52a4ee8fc88cee342"), "user" : "ijk123", "status" : "A", "points" : 0 }
> db.users1.deleteOne({"status" : "A"});
{ "acknowledged" : true, "deletedCount" : 1 }
> db.users1.find({"status" : "A"});
{ "_id" : ObjectId("5bad83a52a4ee8fc88cee342"), "user" : "ijk123", "status" : "A", "points" : 0 }
>
代码语言:txt
复制
    deleteMany()删除匹配条件的多个文档:
代码语言:javascript
复制
> db.users1.find();
{ "_id" : ObjectId("5bad83a52a4ee8fc88cee342"), "user" : "ijk123", "status" : "A", "points" : 0 }
{ "_id" : ObjectId("5bad83a52a4ee8fc88cee343"), "user" : "mop123", "status" : "P", "points" : 0, "comment" : "Pending" }
> db.users1.deleteMany({});
{ "acknowledged" : true, "deletedCount" : 2 }
> db.users1.find();
>
代码语言:txt
复制
    db.users1.deleteMany({})将删除users1集合中的所有文档。
代码语言:txt
复制
    删除集合:
代码语言:javascript
复制
> db.users1.drop();
true
>
代码语言:txt
复制
    删除数据库:
代码语言:javascript
复制
> db.getName();
test
> db.dropDatabase();
{ "ok" : 1 }
>

注意dropDatabase()删除当前正在使用的数据库,所以一定要在执行前检查使用的是哪个数据库。

8. 引用数据库

代码语言:txt
复制
    MongoDB提供了两种方式实现文件间的引用:手动引用或使用DBRef标准。

(1)手动引用

代码语言:txt
复制
     手动引用通过在一个文档中使用另一个文档中的\_id实现。下面是一个手动引用的例子。添加一个新文档,并在其中指定发布者的信息(注意\_id字段):
代码语言:javascript
复制
> apress = ( { "_id" : "Apress", "Type" : "Technical Publisher", "Category" : ["IT",
... "Software","Programming"] } );
{
    "_id" : "Apress",
    "Type" : "Technical Publisher",
    "Category" : [
        "IT",
        "Software",
        "Programming"
    ]
}
> db.publisherscollection.insertOne(apress);
{ "acknowledged" : true, "insertedId" : "Apress" }
>
代码语言:txt
复制
    添加发布者信息之后,在media集合中添加一个的文档,它将指定Apress作为发布者的名字:
代码语言:javascript
复制
> book = ( { "Type" : "Book", "Title" : "Definitive Guide to MongoDB 3rd ed., The", "ISBN" : "978-1-4842-1183-0", "Publisher" : "Apress","Author" : ["Hows, David","Plugge, Eelco","Membrey,Peter","Hawkins, Tim"] } );
{
    "Type" : "Book",
    "Title" : "Definitive Guide to MongoDB 3rd ed., The",
    "ISBN" : "978-1-4842-1183-0",
    "Publisher" : "Apress",
    "Author" : [
        "Hows, David",
        "Plugge, Eelco",
        "Membrey,Peter",
        "Hawkins, Tim"
    ]
}
> db.media.insertOne(book);
{
    "acknowledged" : true,
    "insertedId" : ObjectId("5bad93732a4ee8fc88cee344")
}
>
代码语言:txt
复制
    现在可以使用数据库引用了(这种引用的使用方式和RDBMS中的join毫无可比性)。先将含有发布者信息的文档赋给一个变量:
代码语言:javascript
复制
> book = db.media.findOne({"Publisher" : "Apress"});
{
    "_id" : ObjectId("5baae32464e6602b766d94c0"),
    "Type" : "Book",
    "Title" : " Different Title",
    "ISBN" : "978-1-4842-1183-0",
    "Publisher" : "Apress",
    "Author" : [ ]
}
>
代码语言:txt
复制
    为了获得发布者的信息,可以结合使用findOne()函数和点操作符:
代码语言:javascript
复制
> db.publisherscollection.findOne( { _id : book.Publisher } );
{
    "_id" : "Apress",
    "Type" : "Technical Publisher",
    "Category" : [
        "IT",
        "Software",
        "Programming"
    ]
}
>

(2)使用DBRef引用数据

代码语言:txt
复制
     DBRef提供了文档之间的引用数据的更正式的规范。使用DBRef的主要原因是,引用中文档所在集合可能发生变化。如果引用的一直都是相同的集合,那么手动引用数据也可以。
代码语言:txt
复制
    使用DBRef可以将数据库引用存储为标准的嵌入对象(JSON/BSON)。使用一种标准方式代表引用,意味着驱动和数据框架可以添加辅助方法,以标准的方法操作引用。
代码语言:txt
复制
    添加DBRef引用值的语法如下:
代码语言:javascript
复制
{ $ref : <collectionname>, $id : <id value>[, $db : <database name>] }

<collectionname>代表集合名称;<id value>代表被引用对象的_id字段;通过使用可选的$db可以引用其它数据库中的文档。下面是一个使用了DBRef的样例。首先清空两个集合并添加一个新文档:

代码语言:javascript
复制
> db.publisherscollection.drop();
true
> db.media.drop();
true
> apress = ( { "Type" : "Technical Publisher", "Category" : ["IT","Software","Programming"] } );
{
    "Type" : "Technical Publisher",
    "Category" : [
        "IT",
        "Software",
        "Programming"
    ]
}
> db.publisherscollection.save(apress);
WriteResult({ "nInserted" : 1 })
> 
代码语言:txt
复制
    通过变量名显示其内容:
代码语言:javascript
复制
> apress
{
    "Type" : "Technical Publisher",
    "Category" : [
        "IT",
        "Software",
        "Programming"
    ],
    "_id" : ObjectId("5bad9c3b2a4ee8fc88cee345")
}
>
代码语言:txt
复制
    现在在media集合中添加一个引用该数据的文档:
代码语言:javascript
复制
> book = { "Type" : "Book", "Title" : "Definitive Guide to MongoDB 3rd ed., The", "ISBN" : "978-1-4842-1183-0", "Author": ["Hows, David","Membrey, Peter","Plugge,Eelco","Hawkins, Tim"], Publisher : [ new DBRef ('publisherscollection',apress._id) ] };
{
    "Type" : "Book",
    "Title" : "Definitive Guide to MongoDB 3rd ed., The",
    "ISBN" : "978-1-4842-1183-0",
    "Author" : [
        "Hows, David",
        "Membrey, Peter",
        "Plugge,Eelco",
        "Hawkins, Tim"
    ],
    "Publisher" : [
        DBRef("publisherscollection", ObjectId("5bad9c3b2a4ee8fc88cee345"))
    ]
}
> db.media.save(book);
WriteResult({ "nInserted" : 1 })
> db.media.findOne();
{
    "_id" : ObjectId("5bad9d5f2a4ee8fc88cee346"),
    "Type" : "Book",
    "Title" : "Definitive Guide to MongoDB 3rd ed., The",
    "ISBN" : "978-1-4842-1183-0",
    "Author" : [
        "Hows, David",
        "Membrey, Peter",
        "Plugge,Eelco",
        "Hawkins, Tim"
    ],
    "Publisher" : [
        DBRef("publisherscollection", ObjectId("5bad9c3b2a4ee8fc88cee345"))
    ]
}
>
代码语言:txt
复制
    修改文档所在集合:
代码语言:javascript
复制
> show collections;
media
publisherscollection
> db.publisherscollection.renameCollection("test");
{ "ok" : 1 }
> show collections;
media
test
> db.media.findOne();
{
    "_id" : ObjectId("5bad9d5f2a4ee8fc88cee346"),
    "Type" : "Book",
    "Title" : "Definitive Guide to MongoDB 3rd ed., The",
    "ISBN" : "978-1-4842-1183-0",
    "Author" : [
        "Hows, David",
        "Membrey, Peter",
        "Plugge,Eelco",
        "Hawkins, Tim"
    ],
    "Publisher" : [
        DBRef("publisherscollection", ObjectId("5bad9c3b2a4ee8fc88cee345"))
    ]
}
> db.media.updateOne( { "_id" : ObjectId("5bad9d5f2a4ee8fc88cee346")}, {$set:{Publisher : [ new DBRef ('test',apress._id) ]}} );
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.media.findOne();
{
    "_id" : ObjectId("5bad9d5f2a4ee8fc88cee346"),
    "Type" : "Book",
    "Title" : "Definitive Guide to MongoDB 3rd ed., The",
    "ISBN" : "978-1-4842-1183-0",
    "Author" : [
        "Hows, David",
        "Membrey, Peter",
        "Plugge,Eelco",
        "Hawkins, Tim"
    ],
    "Publisher" : [
        DBRef("test", ObjectId("5bad9c3b2a4ee8fc88cee345"))
    ]
}
> db.test.findOne( { _id : ObjectId("5bad9c3b2a4ee8fc88cee345") } );
{
    "_id" : ObjectId("5bad9c3b2a4ee8fc88cee345"),
    "Type" : "Technical Publisher",
    "Category" : [
        "IT",
        "Software",
        "Programming"
    ]
}
>

9. 使用与索引相关的函数

(1)创建索引

代码语言:javascript
复制
> db.media.createIndex( { Title : 1 } );
{
    "createdCollectionAutomatically" : false,
    "numIndexesBefore" : 1,
    "numIndexesAfter" : 2,
    "ok" : 1
}
>
代码语言:txt
复制
    基于media集合的所有文档的Title值创建出一个索引,:1表示升序,:-1表示降序。
  • 在数组内嵌的键上创建索引
代码语言:javascript
复制
> db.media.insertOne( { "Type" : "CD", "Artist" : "Nirvana","Title" : "Nevermind", "Tracklist" : [ { "Track" : "1", "Title" : "Smells Like Teen Spirit", "Length" : "5:02" }, {"Track" : "2","Title" : "In Bloom", "Length" : "4:15" } ] } );
{
    "acknowledged" : true,
    "insertedId" : ObjectId("5badbcfd2a4ee8fc88cee347")
}
> db.media.createIndex( { "Tracklist.Title" : 1 } );
{
    "createdCollectionAutomatically" : false,
    "numIndexesBefore" : 2,
    "numIndexesAfter" : 3,
    "ok" : 1
}
>
  • 以整个子文档为键创建索引
代码语言:javascript
复制
> db.media.createIndex( { "Tracklist" : 1 } );
{
    "createdCollectionAutomatically" : false,
    "numIndexesBefore" : 3,
    "numIndexesAfter" : 4,
    "ok" : 1
}
>
代码语言:txt
复制
    上面的语句为数组中的所有元素构建索引。这意味着可以使用该索引搜索数组中的任何对象。这些键的类型被称为多键。
  • 创建复合索引
代码语言:javascript
复制
> db.media.createIndex({"Tracklist.Title": 1, "Tracklist.Length": -1});
{
    "createdCollectionAutomatically" : false,
    "numIndexesBefore" : 4,
    "numIndexesAfter" : 5,
    "ok" : 1
}
>

(2)索引相关的命令

  • 强制使用某个索引查询数据
代码语言:javascript
复制
> db.media.find( { ISBN: " 978-1-4842-1183-0"} ) . hint ( { ISBN: -1 } );
Error: error: {
    "ok" : 0,
    "errmsg" : "error processing query: ns=library.mediaTree: ISBN $eq \" 978-1-4842-1183-0\"\nSort: {}\nProj: {}\n planner returned error: bad hint",
    "code" : 2,
    "codeName" : "BadValue"
}
>
代码语言:txt
复制
    可以看到,在没有定义索引的情况下,hint函数会出错。
代码语言:javascript
复制
> db.media.createIndex({ISBN: 1}, {background: true});
{
    "createdCollectionAutomatically" : false,
    "numIndexesBefore" : 5,
    "numIndexesAfter" : 6,
    "ok" : 1
}
> db.media.find( { ISBN: "978-1-4842-1183-0"} ) . hint ( { ISBN: 1 } );
{ "_id" : ObjectId("5bad9d5f2a4ee8fc88cee346"), "Type" : "Book", "Title" : "Definitive Guide to MongoDB 3rd ed., The", "ISBN" : "978-1-4842-1183-0", "Author" : [ "Hows, David", "Membrey, Peter", "Plugge,Eelco", "Hawkins, Tim" ], "Publisher" : [ DBRef("test", ObjectId("5bad9c3b2a4ee8fc88cee345")) ] }
>
代码语言:txt
复制
    如果创建了ISBN键上的索引,查询执行成功。注意第一个命令中的background参数将保证索引在后台完成。默认情况下,索引的建立是在前台进行的,这会阻塞其它写入操作。background选项允许在后台建立索引,而不会阻塞其它写入操作。
代码语言:txt
复制
    为确保使用的是指定的索引,可以使用explain()函数,返回所选择的查询计划的相关信息。其中indexBounds值将显示出所使用的索引:
代码语言:javascript
复制
> db.media.find( { ISBN: "978-1-4842-1183-0"} ) . hint ( { ISBN: 1 } ).explain();
{
    "queryPlanner" : {
        "plannerVersion" : 1,
        "namespace" : "library.media",
        "indexFilterSet" : false,
        "parsedQuery" : {
            "ISBN" : {
                "$eq" : "978-1-4842-1183-0"
            }
        },
        "winningPlan" : {
            "stage" : "FETCH",
            "inputStage" : {
                "stage" : "IXSCAN",
                "keyPattern" : {
                    "ISBN" : 1
                },
                "indexName" : "ISBN_1",
                "isMultiKey" : false,
                "multiKeyPaths" : {
                    "ISBN" : [ ]
                },
                "isUnique" : false,
                "isSparse" : false,
                "isPartial" : false,
                "indexVersion" : 2,
                "direction" : "forward",
                "indexBounds" : {
                    "ISBN" : [
                        "[\"978-1-4842-1183-0\", \"978-1-4842-1183-0\"]"
                    ]
                }
            }
        },
        "rejectedPlans" : [ ]
    },
    "serverInfo" : {
        "host" : "hdp4",
        "port" : 27017,
        "version" : "4.0.2",
        "gitVersion" : "fc1573ba18aee42f97a3bb13b67af7d837826b47"
    },
    "ok" : 1
}
>
  • 限制查询匹配
代码语言:txt
复制
    函数min()和max()用于限制查询匹配,只有在指定的min和max键之间的索引键才会返回。
代码语言:javascript
复制
> db.media.insertOne( { "Type" : "DVD", "Title" : "Matrix, The", "Released" : 1999} );
{
    "acknowledged" : true,
    "insertedId" : ObjectId("5badc41c2a4ee8fc88cee348")
}
> db.media.insertOne( { "Type" : "DVD", "Title" : "Blade Runner", "Released" : 1982 } );
{
    "acknowledged" : true,
    "insertedId" : ObjectId("5badc4222a4ee8fc88cee349")
}
> db.media.insertOne( { "Type" : "DVD", "Title" : "Toy Story 3", "Released" : 2010} );
{
    "acknowledged" : true,
    "insertedId" : ObjectId("5badc4282a4ee8fc88cee34a")
}
> db.media.ensureIndex( { "Released": 1 } );
{
    "createdCollectionAutomatically" : false,
    "numIndexesBefore" : 6,
    "numIndexesAfter" : 7,
    "ok" : 1
}
>
代码语言:txt
复制
    上面的命令先插入了3条记录,然后在Released键上创建升序索引。在MongoDB 3.0以后版本中,ensureIndex()是createIndex()的别名。现在可以使用max()和min()命令:
代码语言:javascript
复制
> db.media.find() . min ( { Released: 1999 } ) . max ( { Released : 2010 } );
{ "_id" : ObjectId("5badc41c2a4ee8fc88cee348"), "Type" : "DVD", "Title" : "Matrix, The", "Released" : 1999 }
> db.media.find() . min ( { Released: 1999 } ) .max ( { Released : 2010 } ). hint ( { Released : 1 } );
{ "_id" : ObjectId("5badc41c2a4ee8fc88cee348"), "Type" : "DVD", "Title" : "Matrix, The", "Released" : 1999 }
>
代码语言:txt
复制
    注意,结果中包含min()值,但不包含max()值。一般来说,建议使用$gt和$lt(分别是大于和小于)而不是min()和max(),因为前者不要求存在索引。函数min()和max()主要用于复合键。
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018年09月28日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 5. 批处理数据
  • 6. 重命名集合
  • 7. 删除数据
  • 8. 引用数据库
  • 9. 使用与索引相关的函数
相关产品与服务
云数据库 MongoDB
腾讯云数据库 MongoDB(TencentDB for MongoDB)是腾讯云基于全球广受欢迎的 MongoDB 打造的高性能 NoSQL 数据库,100%完全兼容 MongoDB 协议,支持跨文档事务,提供稳定丰富的监控管理,弹性可扩展、自动容灾,适用于文档型数据库场景,您无需自建灾备体系及控制管理系统。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档