目录
浅入 MongoDB
结构化数据
MonogoDB 是什么
MongoDB 与关系型数据库
MongoDB 入门命令
文档
.NET Core 示例
如何序列化文档
查询第一条记录
集合
统计数量
查询
不加条件可能导致的问题
查看所有文档
查询结束
转换查询
过滤器
Builders
名称映射
昨天搭建完毕 MongoDB 集群 后,开始计划了解 MongoDB ,并引入使用场景,这里介绍一下学习过程中的一些笔记,帮助读者快速了解 MongoDB 并使用 C# 对其进行编码。
浅入 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 有什么好处?可以参考阿里云的这篇文章:https://developer.aliyun.com/article/64352
整理场景如下:
存储应用程序日志。日志结构化,查找方便,可以导出其它格式和二次利用。
增加字段不需要改动表结构,灵活变更。
支持 json 格式导入;类似 json 的数据结构;能够很容易还原对象的属性,一次性存储数据;如果使用传统数据库,则需要建立多个表并设置主键外界关系。
集群。分布式集群海量数据,容易拓展;故障转移保证服务可用;
解决分布式文件存储需求。
索引方式灵活。
... ...
出处:https://www.cnblogs.com/whuanle/p/13835306.html
微信搜索“DotNet开发跳槽”或扫描文章底部二维码关注公众:回复“.NET5牛”领取海量学习资料。

版权申明:本文来源于网友收集或网友提供,如果有侵权,请转告版主或者留言,本公众号立即删除。





