[聚合文章] MongoDB via C#

c# 2017-10-16 2 阅读

安装

  1. 首先需要安装 MongoDB.Driver 包 nuget
  2. 首先的首先,需要安装好 Mongo 数据库 下载Mongo
  3. 配置好数据库,构建好连接字符串就可以继续使用了 连接字符串

! mongodb 默认是没有用户名和密码的,而且IP和端口都是开放的,请自行做好安全防范的心里准备

数据

数据层次

DataBase

对应 SQL的 Database

Collection

对应 SQL的 Table

Document

对应 SQL的 Row

文档结构

BsonId

对于MongoDB中所有的Document都必须有一个_id字段。

在C#中对于这个"_id"字段可以使用一下的几种操作:

  1. ObjectId [Id|id|_id]
  2. [ValueType|string] [Id|id|_id]

如果吝啬使用Id这个属性名(字段名)的话,也可使用 [BsonId] 这个特性手动的指定映射的Id字段。
不论使用的是以上什么方法,在MongoDB中存储的永远会是 _id 。
当然,也可以不添加该字段,如果不想在查询的时候报错的话,还是需要进行一些额外的操作的。

对于ObjectId类型的_id,可是使用 ObjectId.GenerateNewId() 生成。

几个常用的特性

  1. [BsonId] : (prop) 指定_id字段
  2. [BsonIgnore] : (prop) 在MongoDB中忽略,参考[JsonIgnore]
  3. [BsonRequired] : (prop) 在MongoDB中强制要求
  4. [BsonElement()] : (prop) 指定数据库中的映射
  5. [BsonExtraElements] : (prop) 该字段为扩展字段
  6. [BsonIgnoreExtraElements] : (class) 忽略额外的字段

大部分的特性对于插入的影响不大,对于查询有较大的影响。其中忽略额外元素的特性可以进行丢弃_id的操作。

操作

MongoDB 中增删改都提供了One和Many两组,同步和异步两套,也就是4个操作。

Insert

_collection.InsertOne(new Document(){});
_collection.InsertMany(new List<Document>(){});
_collection.InsertOneAsync(new Document(){});
_collection.InsertManyAsync(new List<Document>(){});

Delete

_collection.DeleteOne(_=>_.id == id);
_collection.DeleteMany(_=>_.userid == userid);
_collection.DeleteOneAsync(_=>_.id == id);
_collection.DeleteManyAsync(_=>_.userid == userid);

Update

_collection.UpdateOne(_=>_.id == id,updateDefinition)
_collection.UpdateMany(_=>_.userid = userid,updateDefinition)
_collection.UpdateOneAsync(_=>_.id == id,updateDefinition)
_collection.UpdateManyAsync(_=>_.userid = userid,updateDefinition)

Query

_collection.Find(_=>_.id == id).First();
_collection.Find(_=>_.id == id).FirstOrDefault();
_collection.Find(_=>_.userid == userid).ToList();
_collection.Find(_=>_.id == id).FirstAsync();
_collection.Find(_=>_.id == id).FirstOrDefaultAsync();
_collection.Find(_=>_.userid == userid).ToListAsync();
await _collection.FindAsync(_=>_.userid == userid);

对于查询的结果还可以进行进一步的操作。

_collection.Find(filter)
            .SortBy(_=>_.CreateTime)
            .Skip(skip)
            .Limit(limt)
            .Project(_=>new ProjectDocument(_))
            .As<Document>()
            .ForEachAsync(func);

Count

_collection.Count(_=>_.userId == userid).Count();
_collection.Count(_=>_.userId == userid).CountAsync();

Query One And

_collection.FindOneAndDelete(_=>_.id == id);
_collection.FindOneAndReplace(_=>_.id == id, new Document());
_collection.FindOneAndUpdate(_=>_.id == id ,updateDefinition);
_collection.FindOneAndDeleteAsync(_=>_.id == id);
_collection.FindOneAndReplaceAsync(_=>_.id == id, new Document());
_collection.FindOneAndUpdateAsync(_=>_.id == id ,updateDefinition);

Definition

以上所有的操作中查找可以使用 filter definition 也可以使用 lambda 表达式,更改则需要使用 update definition .
所有的definition可以使用 Builders<T> 进行创建,也是自行实例化 DefinitionBuilder<T> 然后构建。以下默认习惯性使用Builders<T>进行构建。

Filter Definition

Filter Definition 相当于筛选条件,条件之间可是进行组合。

  1. 简单条件

    var filter = Builders<Document>.Filter.Eq(_=>_.userId,userId);
    _collection.Find(filter).ToList();
    <=>
    _collection.Find(_=>_.userId == userId).ToList();
    
  2. 条件组合

    var filter = Builders<Document>.Filter.Eq(_=>_.userId,userId)
                &Builders<Document>.Filter.Eq(_=>_.title,title);
    
    var filter1 = Builders<Document>.Filter.Eq(_=>_.userId,userId)
                | Builders<Document>.Filter.Eq(_=>_.title,title);
    
    var filter2 = !filter;
    
    <=>
    
    var filter = Builders<Document>.Filter.And(
                            Builders<Document>.Filter.Eq(_=>_.UserId,userid),
                            Builders<Document>.Filter.Eq(_=>_.Title,title)
                            );
    
    var filter1 = Builders<Document>.Filter.Or(
                            Builders<Document>.Filter.Eq(_=>_.UserId,userid),
                            Builders<Document>.Filter.Eq(_=>_.Title,title)
                            );
    var filter2 = Builders<Document>.Filter.Not(filter);
  3. 更多条件

    Builders<Document>.Filter.Lt
    Builders<Document>.Filter.Lte
    Builders<Document>.Filter.Ne
    Builders<Document>.Filter.Gt
    Builders<Document>.Filter.Gte
    Builders<Document>.Filter.Not
    Builders<Document>.Filter.In
    Builders<Document>.Filter.Nin
    Builders<Document>.Filter.Exists
    Builders<Document>.Filter.Regex
    Builders<Document>.Filter.All
    Builders<Document>.Filter.Any
    Builders<Document>.Filter.Size
    Builders<Document>.Filter.SizeGt
    Builders<Document>.Filter.SizeGte
    Builders<Document>.Filter.SizeLt
    Builders<Document>.Filter.SizeLte
    Builders<Document>.Filter.OfType
    
    and more ...

    以上只列举了部分的Filter,点击查看的Filter

Update Definition

Update Definition 是更新条目,相比Filter Definition,Update Definition 可是进行链式操作

Builders<Document>.Update.Set(_=>_.title,title)
                         .Set(_=>_.desc,desc);

相对于SQL来说,MongoDB中提供的Update操作丰富多彩。除了基本的Set,另外还有对于数组的AddToSet、UnSet等,对于时间有CurrentDate等。点击查看所有Update

Aggregate

MongoDB 中提供了聚合操作可是方便的对文档集合进行操作。其中常用的包括了 Group,Match,Project;

_collection.Aggregate().Match(_ => _.UserId==userid)
                       .Group(_ => new {
                            _.Type
                        }, g => new
                        {
                            Type = g.Key,
                            Count = g.Count()
                        })
                       .Project(_ => new
                        {
                            UserId = userid,
                            Type = _.Type,
                            Count = _.Count
                        })
                       .ToList();

需要注意的是,Group和Project中的表达式返回类型对应的都需要是一个对象,在进行映射的时候会转换成BsonDocument,如果直接使用 Group(_=>_.Type,...)这样的操作的话,会抛出 无法将 BsonValue 转化为 BsonDocument 的错误。

Tips

闲时更新

如有错误,多谢指正

注:本文内容来自互联网,旨在为开发者提供分享、交流的平台。如有涉及文章版权等事宜,请你联系站长进行处理。