MongoDB集合结构分析工具Variety

简介:

项目地址: https://github.com/variety/variety


对于MongoDB这种schema-free 的数据库来说,存在数据库里的每一条数据在结构上经常不同,时间长了我们可能就很难去了解库里数据的具体结构了。今天分享一个叫Variety的小脚本,用于对collection中存储的数据情况进行分析。

 

Variety就是一个js脚本,直接使用mongo客户端执行。


一个简单的示例

 

创建一个集合:

1
2
3
4
5
db.users.insert({name:  "Tom" , bio:  "A nice guy." , pets: [ "monkey" "fish" ], someWeirdLegacyKey:  "I like Ike!" });   
db.users.insert({name:  "Dick" , bio:  "I swordfight." , birthday:  new  Date( "1974/03/14" )});    
db.users.insert({name:  "Harry" , pets:  "egret" , birthday:  new  Date( "1984/03/14" )});    
db.users.insert({name:  "Geneviève" , bio:  "?a va?" });    
db.users.insert({name:  "Jim" , someBinData:  new  BinData(2, "1234" )});

 

让我们用这个脚本分析下:

1
$ mongo  test  -- eval  "var collection = 'users'"  variety.js
+------------------------------------------------------------------+
| key                | types              | occurrences | percents |
| ------------------ | ------------       | ----------- | -------- |
| _id                | ObjectId           |           5 |    100.0 |
| name               | String             |           5 |    100.0 |
| bio                | String             |           3 |     60.0 |
| birthday           | String             |           2 |     40.0 |
| pets               | Array(4),String(1) |           5 |     40.0 |
| someBinData        | BinData-old        |           1 |     20.0 |
| someWeirdLegacyKey | String             |           1 |     20.0 |
+------------------------------------------------------------------+

(“test”是我们分析的集合所在的数据库)


看起来每个人都有一个“name”和“_id”。大多数,但不是所有人有“bio”。


有趣的是,“pets”可以是array或者string,但是array比string多。这会在应用程序中导致任何问题么?


上面命令就是在test加的users这个collection上进行数据结构分析。


从上面结果我们能够看出,Variety将所有在users中出现过的字段都进行了统计,包括其类型和数量,以及出现在记录中的频率。这对于我们了解一个collection中的数据是很有用的。比如我们可以很容易看到是否在应该是数字的字段上还出现了一些string类型的值。如果是的话,可能要检查一下代码中是否有类型问题。


似乎创建的第一个文档有一个奇怪的遗留键值 -- 那个构建这个属性类型的蠢蛋没有在之后清理掉。如果有数千个早期的文档,我会参阅基础代码去确认它们不再使用,然后全部删除它们。那样就不会让之后的开发者困惑。


结果存储在varietyResults数据库用于之后的使用。

 

当分析花费很长时间时查看进度

 

查看日志尾部是很好的方法。MongoDB为你提供了“完成百分比”的度量。这些操作对于巨大的集合会花费很长时间。

 

只分析当前的文档


也去你真的有一个非常巨大的集合,你不能一整天一直等着Variety的结果。


也许你想忽略集合的最老的文档,只想看看集合的文档结构是怎样的。


可以应用“limit”约束,只分析集合中的最新文档,像这样:   

1
$ mongo  test  -- eval  "var collection = 'users', limit = 1"  variety.js


让我们更加接近的检查结果:

+----------------------------------------------------+
| key         | types       | occurrences | percents |
| ----------- | ----------- | ----------- | -------- |
| _id         | ObjectId    |           1 |    100.0 |
| name        | String      |           1 |    100.0 |
| someBinData | BinData-old |           1 |    100.0 |
+----------------------------------------------------+


我们只检查了最后一个文档(“limit = 1”)。它属于Geneviève,只包含_id,name和bio列。因此只有这三个键是合理的。

 

分析文档到一个最大深度

 

也许你可能有一个非常深的嵌套对象架构,而你不想深入分析到到一定深度。


可以应用“maxDepth”约束,限制深度,Variety将循环查找以找到新对象。   

1
db.users.insert({name: "Walter" , someNestedObject:{a:{b:{c:{d:{e:1}}}}}});


默认将会一直深入到架构底部:

1
$ mongo  test  -- eval  "var collection = 'users'"  variety.js


+----------------------------------------------------------------+
| key                        | types    | occurrences | percents |
| -------------------------- | -------- | ----------- | -------- |
| _id                        | ObjectId |           1 |    100.0 |
| name                       | String   |           1 |    100.0 |
| someNestedObject           | Object   |           1 |    100.0 |
| someNestedObject.a         | Object   |           1 |    100.0 |
| someNestedObject.a.b       | Object   |           1 |    100.0 |
| someNestedObject.a.b.c     | Object   |           1 |    100.0 |
| someNestedObject.a.b.c.d   | Object   |           1 |    100.0 |
| someNestedObject.a.b.c.d.e | Number   |           1 |    100.0 |
+----------------------------------------------------------------+
1
$ mongo  test  -- eval  "var collection = 'users', maxDepth = 3"  variety.js


+----------------------------------------------------------+
| key                  | types    | occurrences | percents |
| -------------------- | -------- | ----------- | -------- |
| _id                  | ObjectId |           1 |    100.0 |
| name                 | String   |           1 |    100.0 |
| someNestedObject     | Object   |           1 |    100.0 |
| someNestedObject.a   | Object   |           1 |    100.0 |
| someNestedObject.a.b | Object   |           1 |    100.0 |
+----------------------------------------------------------+


如你所见,Variety只是深入了三层。

 

分析一个文档子集

 

也许你有一个巨大的集合,或者你只关心文档的某个子集。


你可以应用“query”约束,使用了一个标准的MongoDB查询对象,在分析前过滤需要的文档子集。   

1
$ mongo  test  -- eval  "var collection = 'users', query = {'caredAbout':true}"  variety.js

 

输出为JSON易于提取和解析

 

Variety支持两种不同的输出格式:   
    . ASCII:很好格式化的表    
    . JSON:有效的JSON结果用于随后其他工具的处理


默认格式是ASCII。你可以通过提供给Variety的属性outputFormat选择格式类型。有效值为ascii和json。

1
$ mongo  test  --quiet -- eval  "var collection = 'users', outputFormat='json'"  variety.js


Quiet选项

 

MongoDB和Variety输出一些额外信息到标准输出。如果你想移除这个信息,你可以使用--quiet选项提供给mongo可执行命令。Variety也可以读取这个选项并减少不必要的输出。同时连接outputFormat=json时是非常有用的。你会只收到JSON,不带有任何其他字符。

1
$ mongo  test  --quiet -- eval  "var collection = 'users', sort = { updated_at : -1 }"  variety.js

 

辅助成员读取

 

在一个繁忙的复制集主成员上分析可能花更长时间比从一个辅助成员读取。为了从辅助成员读取,我们通过设置slaveOk属性为true来告诉MongoDB执行辅助成员读:

1
$ mongo secondary.replicaset.member:31337 /somedb  -- eval  "var collection = 'users', slaveOk = true"  variety.js

 

在MongoDB保存结果用于以后使用

 

默认,Variety只打印结果到标准输出并不存储它们在MongoDB。如果你想自动保存它们在MongoDB用于之后的使用,你可以设置参数persistResults。Variety然后存储结果文档到数据库varietyResults,集合名源自原集合名。如果源集合名是users,Variety将在varietyResults数据库下以集合名usersKeys存储结果。

1
$ mongo  test  --quiet -- eval  "var collection = 'users', persistResults=true"  variety.js


保存到另一个数据库,你可以指定以下参数:   
    . resultsDatabase -- 存储Variety结果的数据库。接受数据库名或者一个host[:port]/database链接地址。    
    . resultsCollection -- 存储Variety结果的集合。警告:在结果插入前该集合删除。    
    . resultsUser -- 结果数据库的用户名    
    . resultsPass -- 结果数据库的密码

1
$ mongo  test  --quiet -- eval  "var collection =  'users' , persistResults= true , resultsDatabase= 'db.example.com/variety'  variety.js


需要注意的是,Variety在对数据结构进行分析的时候,实际是用MapReduce来做的,会进行全表扫描操作,所以如果是对线上库进行分析,那么建议最好使用一个不提供服务的备份库或者在业务低峰来做。避免给线上业务造成压力。

















本文转自UltraSQL51CTO博客,原文链接:http://blog.51cto.com/ultrasql/1753896 ,如需转载请自行联系原作者



相关文章
|
NoSQL MongoDB 数据库
MongoDB 删除集合
10月更文挑战第14天
486 1
|
NoSQL MongoDB 数据库
微服务——MongoDB实战演练——表结构分析
本文档来源于数据库articledb,展示了一张图片资源。图片宽度为1207像素,高度607像素,采用内联显示方式。内容涉及图像处理与样式设定,适用于文档或网页设计中多媒体元素的布局参考。图片来源为cdn.nlark.com,支持webp格式并附带水印处理。
187 1
微服务——MongoDB实战演练——表结构分析
|
存储 JSON NoSQL
|
NoSQL 关系型数据库 MongoDB
接口管理工具深度对比:Apipost与Apifox在Redis/MongoDB支持上的关键差异
近期在团队工具选型时,系统对比了Apifox和Apipost两款接口管理工具,我们的体会是:Apipost适合需要同时管理多种数据库的中大型项目,特别是涉及Redis/MongoDB等非关系型数据库的场景,Apifox仅建议在纯关系型数据库架构且预算有限的小型项目中短期使用。
429 3
|
NoSQL 关系型数据库 MongoDB
微服务——MongoDB常用命令——集合操作
本节主要介绍MongoDB中的集合操作,包括显式与隐式创建集合的方法。显式创建使用`db.createCollection(name)`,需遵循命名规范(如不能以"system."开头或包含`\0`字符)。隐式创建则通过直接向不存在的集合插入文档实现,更为常用。此外,还介绍了集合删除方法`db.collection.drop()`及其返回值规则,帮助用户管理数据库中的集合资源。
504 0
|
存储 NoSQL MongoDB
【赵渝强老师】MongoDB逻辑存储结构
MongoDB的逻辑存储结构由数据库(Database)、集合(Collection)和文档(Document)组成,形成层次化数据模型。用户通过mongoshell或应用程序操作这些结构。视频讲解及结构图详见下文。
395 3
|
NoSQL MongoDB PHP
MongoDB 管理工具: Rockmongo
10月更文挑战第24天
259 1
MongoDB 管理工具: Rockmongo
|
存储 NoSQL 关系型数据库
【赵渝强老师】MongoDB的存储结构
MongoDB 是一个可移植的 NoSQL 数据库,支持跨平台运行。其逻辑存储结构包括数据库、集合和文档,而物理存储结构则由命名空间文件、数据文件和日志文件组成。视频讲解和示意图进一步解释了这些概念。
504 5
|
缓存 NoSQL MongoDB
|
存储 NoSQL MongoDB
MongoDB 查询分析
10月更文挑战第21天
170 1

推荐镜像

更多