浅入 mongodb
monogodb 是什么
mongodb 是 nosql 型数据库,主要特征是存储结构化数据,mongodb 是基于分布式文件存储的开源数据库系统。
结构化数据
以往我们使用 mysql、sqlserver 等数据库,数据都是一条条的。mongodb 的结构化数据正是区别于这种列-行式的数据。
结构化数据具有层级关系:
例如:
{ name: "mongodb", type: "database", count: 1, info: { x: 203, y: 102 } }
mongodb 与关系型数据库
由于 mongodb 中,没有表、行、列,因此初学 mongodb 时可能会有困扰,这里给出一些 mongodb 与 普通sql数据库对应的术语。
sql术语/概念 | mongodb术语/概念 | 解释/说明 |
---|---|---|
database | database | 数据库 |
table | collection | 数据库表/集合 |
row | document | 数据记录行/文档 |
column | field | 数据字段/域 |
index | index | 索引 |
table joins | 非关系型数据库,表与表之间没关系 | |
primary key | primary key | 主键,mongodb自动将_id字段设置为主键 |
资料来源:https://www.runoob.com/mongodb/mongodb-databases-documents-collections.html
mongodb 入门命令
使用 mongo 进入 mongodb shell 后,可使用命令(相当于sql)执行操作。
注: mongodb 中,有一个自动的 _id 字段,此字段 mongodb 自动设置为主键并自动生成值。
显示所有数据库(包含系统数据库):
show dbs
当前正在操作的数据库或集合:
db
连接到指定数据库:
use {数据库名称}
显示所有集合:
show collections # 或 show tables
查看集合中的所有文档:
# mycollection 是集合名称 db.getcollection("mycollection").find() db.getcollection("mycollection").find().limit(1000).skip(0)
可能你不信,笔者百度了很久,第一页没找到一篇合适的友好的 "mongodb 查看集合中的所有文档",特别是 csdn 的垃圾文真的多。建议别瞎折腾了,去下一个 navicat premium,操作的时候,底部会提示所用的命令。
另外 mongodb 有很多实用工具:https://docs.mongodb.com/tools/
文档
mongodb 中的文档(document)即关系型数据库中的一条记录(row)、一行数据。
但, mongodb 中,一个集合(collection-table)中,是不需要具有相同字段的。例如:
a 文档:
{ name: "mongodb", type: "database", count: 1, info: { x: 203, y: 102 } }
b 文档:
{ name: "mongodb", typename: "database", datacount: 1, datainfo: { m: 203, n: 102 } }
.net core 示例
我们从一个基础模板开始。
创建一个控制台程序,打开 nuget 搜索并安装 mongodb.driver
。
var client = new mongoclient("mongodb://{mongodb}:27017"); imongodatabase database = client.getdatabase("test");
集合
可以通过 createcollection()
或 createcollectionasync()
创建一个集合,跟普通数据库不同的是,创建集合时是不需要指定结构的,只需要指定名称即可:
await database.createcollectionasync("test");
获取集合
getcollection()
函数可以让我们获取到集合,如果集合不存在,则会自动创建。
imongocollection<tdocument> getcollection<tdocument>()
由于同一个集合可以有不同字段和字段类型的文档,因此几个文档如果有所差别,是很难统一起来的,例如:
(n/a) 代表此文档没有这个字段;如果一个文档有 10 个字段,另一个文档有 8 个字段,但是两者的字段完全不同时,要合并起来来,就有 18 个字段了。很明显,不应该汇集在一起,而是应该使用强类型对其 ”归档“ 。
创建两个类,分别为 test1,test2,其内容如下:
public class test1 { public string name { get; set; } } public class test2 { public string datatype { get; set; } }
以两种文档类型获取集合:
var collection1 = database.getcollection<test1>("test"); var collection2 = database.getcollection<test2>("test");
这个获取集合的意思是,获取此集合中这类格式的文档的操作能力。
往集合中插入数据:
collection1.insertone(new test1 { name = "test1" }); collection2.insertone(new test2 { datatype = "test2" }); // await collection.insertoneasync(object);
启动,查看结果。
insertmany()
可以插入批量数据:
test1[] datas = new test1[] { new test1 { name = "test1" } }; collection1.insertmany(datas);
统计数量
获取集合中所有的文档数:
collection1.countdocuments(new bsondocument()) // await collection1.countdocumentsasync(new bsondocument());
任意一个文档集合对象,使用 countdocuments(new bsondocument())
都是获得此集合的所有文档数,而不是此类型的文档数。例如:
var collection1 = database.getcollection<test1>("test"); collection1.countdocuments(new bsondocument())
获取的并不是 test1 类型的文档数量,而是整个集合所有文档的数量。
原因是,countdocuments()
是一个过滤器函数,可以使用指定条件来筛选符合条件的文档的数量。指定条件后面会介绍。
查询
mongodb 的查询并不像 linq 中的表达式,基础了 ienumerable
或 ienumerable<t>
接口,因此驱动没有 where
、select
这种表达式的查询方法。
find()
函数是查询函数,里面可以添加丰富的表达式,来筛选文档,当数据加载到本地内存后,即可使用丰富的表达式。
bsondocument
是一个类型,代表了要查询的文档筛选条件,如果 bsondocument
对象没有添加任何属性,则代码没有筛选参数,则默认所有文档都符号条件。
我们把 test1 和 test2 类型,都加上一个属性:
public objectid _id { get; set; }
不然会报格式化错误:system.formatexception
如何序列化文档
document
是文档对象, jsonserializer 是 system.text.json 的静态类。
console.writeline(jsonserializer.serialize(document));
查询第一条记录
var document = collection1.find(new bsondocument()).firstordefault();
不加条件可能导致的问题
以下代码会导致程序报错:
var documents = await collection1.find(new bsondocument()).tolistasync(); foreach(var item in documents) { console.writeline(jsonserializer.serialize(item)); }
因为 collection1
是标记为 test1
的文档集合;但是 .find(new bsondocument())
是查询集合中的所有文档,因此获取到 test2。
但是 test2 是不能转为 test1 的,因此,会导致程序报错。
查看所有文档
var documents = collection1.find(new bsondocument()).tolist(); var documents = await collection1.find(new bsondocument()).tolistasync();
前面已经说过,如果集合中存在其它格式的文档,获取全部文档时,因为 test2 跟 test1 没任何关系,会导致 mongodb.driver
报错。
如果文档数量比较大,要使用异步的 foreachasync()
查询,其原理是 回调。
list<test1> tests = new list<test1>(); action<test1> action = item => { tests.add(item); console.writeline(jsonserializer.serialize(item)); }; await collection1.find(new bsondocument()).foreachasync(action);
查询结束
使用 find()
以及后续函数查询后,要结束查询(延迟加载),可以使用 tocursor()
函数结束,程序会立即开始查询并将数据返回内存。
转换查询
使用 toenumerable()
可以使用 linq 来查询文档。
var list = collection1.find(new bsondocument()).tocursor().toenumerable();
过滤器
前面我们查询的时候都使用 .find(new bsondocument())
,bsondocument
是过滤器对象,里面存储了过滤的规则,但是我们不能直接设置 new bsondocument()
中的属性,而是使用构建器filterdefinitionbuilder
对象,而此对象可以通过 mongodb.driver.builders<tdocument>.filter
创建 。
假设有以下数据集(文档):
5f8bdf88e63d14cb5f01dd85 小明 19 5f8bdf88e63d14cb5f01dd86 小红 20 5f8bdf88e63d14cb5f01dd87 小张 16 5f8bdf88e63d14cb5f01dd88 小小 17 # -----插入数据的代码----- public class test { public objectid _id { get; set; } public string name { get; set; } public int age { get; set; } } var datas = new test[] { new test{ name="小明",age=19}, new test{ name="小红",age=20}, new test{ name="小张",age=16}, new test{ name="小小",age=17} }; collection.insertmany(datas);
使用构建器:
filterdefinition<test> filter = builders<test>.filter
查询 age 大于 18 的文档:
filterdefinition<test> filter = filterbuilder.where(item => item.age >= 18);
获取结果:
test[] documents = collection.find(filter).toenumerable<test>().toarray();
过滤器还有 gt()
、in()
、lte()
等非 linq 的函数,需要查看文档学习。
builders<tdocument>
builders<tdocument>
除了能够生成过滤构建器,还有其它几种构建器:
// 条件过滤 public static filterdefinitionbuilder<tdocument> filter { get; } // 索引过滤 public static indexkeysdefinitionbuilder<tdocument> indexkeys { get; } // 映射器,相当于使用 linq 的 .select() 查询自己只需要的字段 public static projectiondefinitionbuilder<tdocument> projection { get; } // 排序,创建排序规则,如工具年龄排序 public static sortdefinitionbuilder<tdocument> sort { get; } // 更新,更新某些字段的值等 public static updatedefinitionbuilder<tdocument> update { get; }
详细请参考 https://mongodb.github.io/mongo-csharp-driver/2.10/reference/driver/definitions/#projections
名称映射
由于 mongodb 区分字段的大小写,文档的字段一般使用驼峰命名法,首字母小写,而 c# 字段属性首字母是 大小开头的,因此需要不同名称对应起来。
可以使用 bsonelement
特性来设置映射的名称。
class person { [bsonelement("fn")] public string firstname { get; set; } [bsonelement("ln")] public string lastname { get; set; } }
以上就是 mongodb 的初入门知识,但是使用了 mongodb 有什么好处?可以参考这篇文章:
整理场景如下:
存储应用程序日志。日志结构化,查找方便,可以导出其它格式和二次利用。
增加字段不需要改动表结构,灵活变更。
支持 json 格式导入;类似 json 的数据结构;能够很容易还原对象的属性,一次性存储数据;如果使用传统数据库,则需要建立多个表并设置主键外界关系。
集群。分布式集群海量数据,容易拓展;故障转移保证服务可用;
解决分布式文件存储需求。
索引方式灵活。
到此这篇关于mongodb数据库介绍并用.net core对其进行编码的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持代码网。
发表评论