-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
lidanger
committed
Apr 20, 2019
1 parent
d8032c7
commit 43d8ae0
Showing
43 changed files
with
4,843 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
`BsonDocument`类是LiteDB文档的一个实现。`BsonDocument`内部在一个`Dictionary<string, BsonValue>`中存储键值对。 | ||
|
||
|
||
```C# | ||
var customer = new BsonDocument(); | ||
customer["_id"] = ObjectId.NewObjectId(); | ||
customer["Name"] = "John Doe"; | ||
customer["CreateDate"] = DateTime.Now; | ||
customer["Phones"] = new BsonArray { "8000-0000", "9000-000" }; | ||
customer["IsActive"] = true; | ||
customer["IsAdmin"] = new BsonValue(true); | ||
customer.Set("Address.Street", "Av. Protasio Alves, 1331"); | ||
``` | ||
|
||
关于文档字段 **keys**: | ||
|
||
- Keys 只包含字符,数字或`_`和`-` | ||
- Keys 是区分大小写的 | ||
- 不允许重复键 | ||
- LiteDB保持原始键顺序,包括映射的类。仅有的例外是`_id`字段,它会一直是第一个字段。 | ||
|
||
关于文档字段 **values**: | ||
|
||
- Values 可以是任意BSON数据类型: Null, Int32, Int64, Double, String, Embedded Document, Array, Binary, ObjectId, Guid, Boolean, DateTime, MinValue, MaxValue | ||
- 当一个字段被索引,它的值在BSON序列化后必须小于512字节。 | ||
- 无索引的值本身没有大小限制,但整个文档BSON序列化限制为1Mb。这个大小包括BSON使用的所有额外字节。 | ||
- `_id` 字段不能是: `Null`, `MinValue` or `MaxValue` | ||
- `_id` 是唯一索引字段,因此值必须小于512字节 | ||
|
||
关于.NET类 | ||
|
||
- `BsonValue` | ||
- 这个类可以保存任何BSON数据类型,包括null,数组或文档。 | ||
- 对所有支持的.NET数据类型有一个隐式构造器 | ||
- 值不会变化 | ||
- `RawValue` 属性返回内部.NET对象实例 | ||
- `BsonArray` | ||
- 支持 `IEnumerable<BsonValue>` | ||
- 每一个数组项可以有不同的BSON类型对象 | ||
- `BsonDocument` | ||
- 缺失字段总是返回`BsonValue.Null`值 | ||
- `Set` 和 `Get` 方法可以配合点分表示法(dotted notation)用于访问/创建内部文档 | ||
|
||
```C# | ||
// 测试BSON值数据类型 | ||
if(customer["Name"].IsString) { ... } | ||
|
||
// 辅助获取.NET类型 | ||
string str = customer["Name"].AsString; | ||
``` | ||
|
||
要使用其他.NET数据类型,你需要一个自定义`BsonMapper`类。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
文档被存储和组织在集合中。`LiteCollection`在LiteDB中是一个管理集合的通用类。每一个集合必须有一个唯一名称: | ||
|
||
- 只包含字母,数字和`_` | ||
- 集合名称是 **区分大小写的** | ||
- 以`_`开头的集合名称被保留,内部使用 | ||
|
||
全部集合名称加起来被限制在3000个字节以内。如果你有很多集合的话,请使用短名称。如果每一个集合名称使用大约10个字节,在一个单数据库中,你可以拥有~300个集合。 | ||
|
||
集合在第一个`Insert` 或 `EnsureIndex`操作时自动创建。在一个不存在的的集合中运行查询,删除或更新并不会创建集合。 | ||
|
||
对无模式文档来说,`LiteCollection<T>`是一个通用类,它作为`BsonDocument`可以与`<T>`一起使用。LiteDB在内部会转换`T`为`BsonDocument`,并且所有操作都使用这个通用文档。 | ||
|
||
在这个例子中,两个代码片段产生同样的结果。 | ||
|
||
```C# | ||
// 强类型类 | ||
using(var db = new LiteDatabase("mydb.db")) | ||
{ | ||
// 获取集合实例 | ||
var col = db.GetCollection<Customer>("customer"); | ||
|
||
// 向集合插入一个文档 - 如果集合不存在,现在创建 | ||
col.Insert(new Customer { Id = 1, Name = "John Doe" }); | ||
|
||
// 如果Name字段不存在索引,在Name字段上创建新索引 | ||
col.EnsureIndex(x => x.Name); | ||
|
||
// 现在,搜索你想要的文档 | ||
var customer = col.FindOne(x => x.Name == "john doe"); | ||
} | ||
|
||
// 通用 BsonDocument | ||
using(var db = new LiteDatabase("mydb.db")) | ||
{ | ||
// 获取集合实例 | ||
var col = db.GetCollection("customer"); | ||
|
||
// 向集合插入一个文件 - 如果集合不存在,现在创建 | ||
col.Insert(new BsonDocument().Add("_id", 1).Add("Name", "John Doe")); | ||
|
||
// 如果Name字段不存在索引,在Name字段上创建新索引 | ||
col.EnsureIndex("Name"); | ||
|
||
// 现在,搜索你想要的文档 | ||
var customer = col.FindOne(Query.EQ("Name", "john doe")); | ||
} | ||
``` | ||
### LiteDatabase API 实例方法 | ||
|
||
- **`GetCollection<T>`** - 这个方法返回`LiteCollection`的一个实例。如果省略`<T>`,`<T>`为`BsonDocument`。这是仅有的获取一个集合实例的方式。 | ||
- **`RenameCollection`** - 仅重命名一个集合名称 - 不改变任何文档 | ||
- **`CollectionExists`** - 检查一个集合是否已经存在于数据库中 | ||
- **`GetCollectionNames`** - 获取数据库中的所有集合名称 | ||
- **`DropCollection`** - 删除数据库上的所有文档,所有索引和集合引用 | ||
|
||
### LiteCollection API 实例方法 | ||
|
||
- **`Insert`** - 插入一个新文档或一个文档`IEnumberable`。如果你的文档没有`_id`字段,Insert操作会使用`ObjectId`创建一个新的。如果你有一个映射过的对象,可以使用 `AutoId`。参考 [Object Mapping](Object-Mapping) | ||
- **`InsertBulk`** - 用于插入大量文档。将文档分批次,每一批控制一次事务。这个方法每批插入后会清理缓存以保持内存使用率。 | ||
- **`Update`** - 更新按`_id`字段标识的文档。如果没找到,返回false | ||
- **`Delete`** - 按`_id`或一个`Query`删除文档。如果没找到,返回false | ||
- **`Find`** - 使用LiteDB查询查找文档。参考 [Query](Query) | ||
- **`EnsureIndex`** - 在一个字段上创建新索引。参考 [Indexes](Indexes) | ||
- **`DropIndex`** - 删除一个存在的索引 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
LiteDatabase可以使用一个连接字符串初始化,语法为`key1=value1; key2=value2; ...`。如果你的连接字符串中没有`;`,LiteDB假定你的连接字符串是Filename键。键不分大小写。 | ||
|
||
### 选项 | ||
|
||
- **`Filename`** (string): 从DLL目录起始的完整路径或相对路径。 | ||
- **`Journal`** (bool): 启用或禁用浮点写检查来确保持久性(默认: true) | ||
- **`Password`** (string): 使用一个密码加密(使用AES)你的数据文件(默认: null - 未加密) | ||
- **`Cache Size`** (int): 缓存页面的最大数量。超过这个大小,会将数据存在磁盘中以防止使用过多内存(默认: 5000) | ||
- **`Timeout`** (TimeSpan): 等待解锁操作的超时时间(线程锁或锁定文件) | ||
- **`Mode`** (Exclusive|ReadOnly|Shared): 怎样打开数据文件(默认: NET35,`Shared`,NetStandard,`Exclusive`) | ||
- **`Initial Size`** (string|long): 如果数据库是新的,分配初始空间大小 - 支持 KB, MB, GB (默认: null) | ||
- **`Limit Size`** (string|long): 数据文件的大小限制 - 支持 KB, MB, GB (默认: null) | ||
- **`Upgrade`** (bool): 如果为true,尝试从旧版本(v2)升级数据文件(默认: null) | ||
- **`Log`** (byte): 数据库调试信息 - 使用`LiteDatabase.Log` (默认: Logger.NONE) | ||
- **`Async`** (bool): 支持"sync over async" 文件流创建,以便在UWP中用来访问任何磁盘文件夹(只用于NetStandard, 默认: false) | ||
|
||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
LiteDB按文档方式存储数据,这种文档是JSON风格的键值对。文档是无模式的数据结构。每一个文档同时包含你的数据和结构。 | ||
|
||
```JS | ||
{ | ||
_id: 1, | ||
name: { first: "John", last: "Doe" }, | ||
age: 37, | ||
salary: 3456.0, | ||
createdDate: { $date: "2014-10-30T00:00:00.00Z" }, | ||
phones: ["8000-0000", "9000-0000"] | ||
} | ||
``` | ||
|
||
- `_id` 包含文档主键 - 集合中的一个唯一值 | ||
- `name` 包含一个嵌入文档,有`first`和`last`两个字段 | ||
- `age` 包含一个`Int32`值 | ||
- `salary` 包含一个`Double`值 | ||
- `createDate` 包含一个`DateTime`值 | ||
- `phones` 包含一个`String`数组 | ||
|
||
LiteDB在集合中存储文档。一个集合是一组相关的文档,它们有一组共享的索引。集合类似于关系数据库的一个表。 | ||
|
||
### BSON | ||
|
||
LiteDB使用BSON(二进制JSON)数据格式存储文档。BSON是包含有额外类型信息的一个JSON二进制表示法。在文档中,字段值可以是任意BSON数据类型,包括其他的文档,数组和文档数组。BSON是一种简单、快速地将文档序列化为二进制的方式。 | ||
|
||
LiteDB使用[BSON 数据类型](http://bsonspec.org/spec.html)的一个子集。如下为所有支持的LiteDB BSON数据类型和.NET对应关系。 | ||
|
||
|BSON 类型 |.NET 类型 | | ||
|----------|------------------------------------------------------------| | ||
|MinValue |- | | ||
|Null |Any .NET object with `null` value | | ||
|Int32 |`System.Int32` | | ||
|Int64 |`System.Int64` | | ||
|Double |`System.Double` | | ||
|Decimal |`System.Decimal` | | ||
|String |`System.String` | | ||
|Document |`System.Collection.Generic.Dictionary<string, BsonValue>` | | ||
|Array |`System.Collection.Generic.List<BsonValue>` | | ||
|Binary |`System.Byte[]` | | ||
|ObjectId |`LiteDB.ObjectId` | | ||
|Guid |`System.Guid` | | ||
|Boolean |`System.Boolean` | | ||
|DateTime |`System.DateTime` | | ||
|MaxValue |- | | ||
|
||
### 扩展 JSON | ||
|
||
要序列化一个文档为JSON,LiteDB使用一个扩展版本的JSON,这样不会丢失任何不存在于JSON中的BSON类型信息。扩展数据类型被表示为一个嵌入文档,用`$`作为初始键,并且值是字符串。 | ||
|
||
|BSON 数据类型 |JSON 表示法 |描述 | | ||
|--------------|------------------------------------------------------|-----------------------------------| | ||
|ObjectId |`{ "$oid": "507f1f55bcf96cd799438110" }` |12 bytes in hex format | | ||
|Date |`{ "$date": "2015-01-01T00:00:00Z" }` |UTC and ISO-8601 format | | ||
|Guid |`{ "$guid": "ebe8f677-9f27-4303-8699-5081651beb11" }` | | | ||
|Binary |`{ "$binary": "VHlwZSgaFc3sdcGFzUpcmUuLi4=" }` |Byte array in base64 string format | | ||
|Int64 |`{ "$numberLong": "12200000" }` | | | ||
|Decimal |`{ "$numberDecimal": "122.9991" }` | | | ||
|MinValue |`{ "$minValue": "1" }` | | | ||
|MaxValue |`{ "$maxValue": "1" }` | | | ||
|
||
LiteDB在它的`JsonSerializer`静态类中实现JSON。序列化和反序列化只接受`BsonValue`作为输入/输出。如果你想转换你的对象类型为一个BsonValue,你需要使用一个`BsonMapper`。 | ||
|
||
```C# | ||
var customer = new Customer { Id = 1, Name = "John Doe" }; | ||
|
||
var doc = BsonMapper.Global.ToDocument(customer); | ||
|
||
var jsonString = JsonSerialize.Serialize(doc, pretty, includeBinaryData); | ||
``` | ||
|
||
`JsonSerialize`也支持`TextReader` 和 `TextWriter`从一个文件或`Stream`中直接读/写。 | ||
|
||
### ObjectId | ||
|
||
`ObjectId`是一个12字节BSON类型: | ||
|
||
- `Timestamp`: 表示Unix时间以来的秒数的值 | ||
- `Machine`: 机器标识 (3字节) | ||
- `Pid`: 进程标识 (2字节) | ||
- `Increment`: 一个计数器,开始于一个随机值(3字节) | ||
|
||
在LiteDB中,文档被存储在集合中时,需要一个唯一的`_id`字段来作为主键。因为`ObjectIds`很小,唯一性很高,并且生成很快,LiteDB使用`ObjectIds`作为`_id`字段未指定时的默认值 | ||
|
||
不同于Guid数据类型,ObjectIds是有序的,因此更适合于索引。ObjectIds使用十六进制数字的字符串表示。 | ||
|
||
```C# | ||
|
||
var id = ObjectId.NewObjectId(); | ||
|
||
// 你可以从一个ObjectId获取创建时间 | ||
var date = id.CreationTime; | ||
|
||
// ObjectId 用十六进制值表示 | ||
Debug.WriteLine(id); | ||
"507h096e210a18719ea877a2" | ||
|
||
// 基于十六进制表示法创建一个实例 | ||
var nid = new ObjectId("507h096e210a18719ea877a2"); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
LiteDB是一个文档数据库,因此集合间没有连接。你可以使用嵌入文档(子文档)或在集合间创建一个引用。要创建这个引用,你可以使用`[BsonRef]`属性,或从Fluent API映射器中使用`DbRef`方法。 | ||
|
||
### 在数据库初始化时映射一个引用 | ||
|
||
```C# | ||
public class Customer | ||
{ | ||
public int CustomerId { get; set; } | ||
public string Name { get; set; } | ||
} | ||
|
||
public class Order | ||
{ | ||
public int OrderId { get; set; } | ||
public Customer Customer { get; set; } | ||
} | ||
``` | ||
|
||
如果你不做任何映射,当你保存一个`Order`,`Customer`会被保存为一个嵌入的文档(没有链接到任何其他集合)。如果你改变`Customer`集合中的顾客名称,这个更改不会影响`Order`集合。 | ||
|
||
```JS | ||
Order => { _id: 123, Customer: { CustomerId: 99, Name: "John Doe" } } | ||
``` | ||
|
||
如果你想顾客引用只存储在`Order`集合,你可以装饰你的类: | ||
|
||
```C# | ||
public class Order | ||
{ | ||
public int OrderId { get; set; } | ||
|
||
[BsonRef("customers")] // 这里"customers"是Customer集合名称 | ||
public Customer Customer { get; set; } | ||
} | ||
``` | ||
|
||
或使用Fluent API: | ||
|
||
```C# | ||
BsonMapper.Global.Entity<Order>() | ||
.DbRef(x => x.Customer, "customers"); // 这里"customers"Customer集合名称 | ||
``` | ||
|
||
现在,当你存储`Order`时,你将只存储链接引用。 | ||
|
||
```JS | ||
Order => { _id: 123, Customer: { $id: 4, $ref: "customers"} } | ||
``` | ||
|
||
### 查询结果 | ||
|
||
当你使用一个交叉集合引用查询一个文档,你可以在查询前使用`Include`方法自动加载引用。 | ||
|
||
```C# | ||
var orders = db.GetCollection<Order>("orders"); | ||
|
||
var order1 = orders | ||
.Include(x => x.Customer) | ||
.FindById(1); | ||
``` | ||
|
||
DbRef也支持`List<T>` 或 `Array`,像这样: | ||
|
||
```C# | ||
public class Product | ||
{ | ||
public int ProductId { get; set; } | ||
public string Name { get; set; } | ||
public decimal Price { get; set; } | ||
} | ||
|
||
public class Order | ||
{ | ||
public int OrderId { get; set; } | ||
public DateTime OrderDate { get; set; } | ||
public List<Product> Products { get; set; } | ||
} | ||
|
||
BsonMapper.Global.Entity<Order>() | ||
.DbRef(x => x.Products, "products"); | ||
``` | ||
|
||
如果从数据文件恢复时你的`Products`字段是null或空列表,LiteDB将什么也不做(respect)。如果你在查询中不使用`Include`,类被加载时,只会设置`ID`(所有其他属性会一直是默认/null值)。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
LiteDB限制一个文档大小为1Mb,以保持内存占用不是很大。对于文本文档来说,这是一个很大的尺寸。但对于很多二进制文件来说,1Mb就太小了。因此LiteDB实现了`FileStorage`,一个用于存储文件和流的自定义集合。 | ||
|
||
LiteDB使用两个特殊的集合来分裂文件内容到多个分块(chunks): | ||
|
||
- `_files` 集合只存储文件引用和元数据 | ||
|
||
```JS | ||
{ | ||
_id: "my-photo", | ||
filename: "my-photo.jpg", | ||
mimeType: "image/jpg", | ||
length: { $numberLong: "2340000" }, | ||
uploadDate: { $date: "2015-01-01T00:00:00Z" }, | ||
metadata: { "key1": "value1", "key2": "value2" } | ||
} | ||
``` | ||
|
||
- `_chunks` 集合按1MB分块存储二进制数据。 | ||
|
||
```JS | ||
{ | ||
_id: "my-photo\00001", | ||
data: { $binary: "VHlwZSAob3Igc ... GUpIGhlcmUuLi4" } | ||
} | ||
{ | ||
_id: "my-photo\00002", | ||
data: { $binary: "pGaGhlcmUuLi4 ... VHlwZSAob3Igc" } | ||
} | ||
{ | ||
... | ||
} | ||
``` | ||
|
||
文件用`_id`字符串值标识,遵循下列规则: | ||
|
||
- 以字符,数字,`_`, `-`, `$`, `@`, `!`, `+`, `%`, `;` 或 `.` 开头 | ||
- 如果包含一个 `/`,必须紧跟以上字符 | ||
|
||
要更好地组织很多文件,你可以使用`_id`作为一个`directory/file_id`。这是一个不错的方案,这样可以使用`Find`方法快速查找一个文件夹下的所有文件。 | ||
|
||
示例: `$/photos/2014/picture-01.jpg` | ||
|
||
`FileStorage`集合包含简单的方法,如: | ||
|
||
- **`Upload`**: 发送文件或流到数据库。可以用于文件或`Stream`。如果文件已存在,文件内容会被覆盖。 | ||
- **`Download`**: 从数据库获取你的文件,并复制到`Stream`参数。 | ||
- **`Delete`**: 删除一个文件引用和所有数据分块 | ||
- **`Find`**: 在`_files`集合中查找很多文件中的一个。返回`LiteFileInfo`类,稍后它可以用于下载数据。 | ||
- **`SetMetadata`**: 更新已存储文件的元数据。这个方法不改变已存储文件的值。它更新`_files.metadata`的值。 | ||
- **`OpenRead`**: 按`_id`查找文件,并返回一个`LiteFileStream`将文件内容读取为流 | ||
|
||
```C# | ||
// 从文件系统上传一个文件 | ||
db.FileStorage.Upload("$/photos/2014/picture-01.jpg", @"C:\Temp\picture-01.jpg"); | ||
|
||
// 从一个流上传一个文件 | ||
db.FileStorage.Upload("$/photos/2014/picture-01.jpg", stream); | ||
|
||
// 只查找文件引用 - 如果没有找到返回null | ||
LiteFileInfo file = db.FileStorage.FindById("$/photos/2014/picture-01.jpg"); | ||
|
||
// 现在,加载二进制数据并保存到文件系统 | ||
file.SaveAs(@"C:\Temp\new-picture.jpg"); | ||
|
||
// 或者获取二进制数据为流并复制到另一个流 | ||
file.CopyTo(Response.OutputStream); | ||
|
||
// 查找一个"directory"中的所有文件引用 | ||
var files = db.FileStorage.Find("$/photos/2014/"); | ||
``` | ||
|
||
`FileStorage`不支持事务,以防止将变化保存到磁盘前,把文件的所有内部都放进内存。但每个数据分块都使用事务。每个上传的数据分块都在一个单独的事务中提交。 | ||
|
||
当上传每一个分块时,`FileStorage`在地址`0`位置保存`_files.length`。当所有分块上传完成时,`FileStorage`对每一个分块的大小进行合计并更新`_files.length`。如果你尝试下载一个0字节长度的文件,下载的文件将是损坏的。一个毁坏的文件并不一定意味着一个损坏的数据库。 |
Oops, something went wrong.