.net core操作MongoDB

2023-01-07 18:01:16

前言

現實中認識的一個搞java(百萬富婆)的大佬,已經轉行做抖音主播了,搞技術的只能趕在年前再水一篇部落格,不足之處歡迎拍磚,以免誤人子弟,呔,真是太難受了

環境準備

  • .net core 3.1
  • MongoDB
  • Navicat Premium 16

建立專案

1.選擇ASP.NET Core Web API 專案模板

2.設定專案資訊 專案名稱,專案路徑

3.設定專案其它資訊,這裡選擇使用.net core 3.1 不設定https

新增依賴

1.獲取MongoDB.Driver包 版本 2.18.0

方案A. install-package MongoDB.Driver
方案B. nuget包管理工具搜尋 MongoDB.Driver
方案C. 選中專案,雙擊,新增
<ItemGroup>
    <PackageReference Include="MongoDB.Driver" Version="2.18.0" />
</ItemGroup>

註冊中介軟體

1.新增組態檔

"MongoDB": {
"ConnName": "mongodb://root:[email protected]:27017/",
"DatabaseName": "test"
}

2.新增設定類

public class MongoDBConfig
{
    /// <summary>
    /// 連線字串
    /// </summary>
    public string ConnName { get; set; }

    /// <summary>
    /// 資料庫名稱
    /// </summary>
    public string DatabaseName { get; set; }
}

3.註冊組態檔與中介軟體

//讀取組態檔
var mongoDBOptions = Configuration.GetSection("MongoDB").Get<MongoDBConfig>();

//註冊設定
services.Configure<MongoDBConfig>(this.Configuration.GetSection("MongoDB"));

//註冊中介軟體
services.AddSingleton(new MongoClient(mongoDBOptions.ConnName));

其實就是註冊了一個mongodb的使用者端範例,然後用這個使用者端範例來實現crud,如果你想優雅點(強迫症),也可以自定義一個拓展,來註冊這個範例,這是一個通用技巧,後面使用到的類請自行註冊

public static class MongoDBExtensions 
{
    public static void AddMongoDB(this IServiceCollection services, Action<MongoDBConfig> setupAction)
    {
        if (setupAction == null)
        {
            throw new ArgumentNullException(nameof(setupAction));
        }
        var options = new MongoDBConfig();
        setupAction(options);
        services.Configure(setupAction);
        services.AddSingleton(services.AddSingleton(new MongoClient(options.ConnName)));
    }
}

使用拓展,來註冊中介軟體

var mongoDBOptions = Configuration.GetSection("MongoDB").Get<MongoDBConfig>();
services.AddMongoDB(m => 
{
    m.ConnName = mongoDBOptions.ConnName;
    m.DatabaseName = mongoDBOptions.DatabaseName;
});

封裝基礎操作

最常用的辦法,就是弄個DBHelper類,這種簡單粗暴的方式,在.net core裡使用並不優雅(網上教學太多了,不想重複的水),這裡模擬常規的倉儲模式,進行演示

1.建立 Service,Repertoty,Model 資料夾
2.建立 BaseDbContext 類

public class BaseDbContext
{
    private readonly IMongoDatabase _database;
    public BaseDbContext(MongoClient client, IOptions<MongoDBConfig> options)
    {
        //決定使用哪個庫
        _database = client.GetDatabase(options.Value.DatabaseName);
    }

    /// <summary>
    /// 資料庫物件
    /// </summary>
    public IMongoDatabase MongoDatabase { get{ return _database; } }
}

如果專案只操作一個資料庫,直接在基礎類別裡指定操作的資料庫即可,如果需要操作多個資料庫,可以再新建一個子類(TestDbContext),在子類裡指定要操作的資料庫
前面我已經註冊了mongodb的使用者端跟組態檔,所以在Startup類下,可以直接註冊這個類,容器會自動管理這些依賴

services.AddSingleton(typeof(BaseDbContext));

如果你想更優雅點(強迫症),可以建立一個IBaseDbContext 介面,在介面裡定義相關的規範

services.AddSingleton<IBaseDbContext>();

3.建立 BaseRepertoty 類

public class BaseRepertoty<T> where T : class, new()
{
    private readonly IMongoDatabase _database;

    private readonly string _collName;

    public BaseRepertoty(BaseDbContext baseDbContext) 
    {
        _database = baseDbContext.MongoDatabase;
        _collName = typeof(T).GetAttributeValue((TableAttribute m) => m.Name);
        _collName = _collName ?? typeof(T).Name;

    }
}

前面我們已經註冊了BaseDbContext,它的主要作用是確定操作的庫,那BaseRepertoty就是對具體集合(表)的操作,這裡使用泛型,避免重複的CRUD操作
我新建了一個拓展,用於獲取實體類上真實集合(表)的名稱,如果使用者沒有指定,則取實體類的類名,做為集合(表)的名稱

public static class AttributeExtensions
{
    public static TValue GetAttributeValue<TAttribute, TValue>(
        this Type type,
        Func<TAttribute, TValue> valueSelector)
        where TAttribute : Attribute
    {
        var att = type.GetCustomAttributes(
            typeof(TAttribute), true
        ).FirstOrDefault() as TAttribute;
        if (att != null)
        {
            return valueSelector(att);
        }
        return default(TValue);
    }
}

4.建立 UserInfoRepertoty 類

public class UserInfoRepertoty : BaseRepertoty<UserInfo>
{
    public UserInfoRepertoty(BaseDbContext baseDbContext) : base(baseDbContext) 
    {

    }
}

它的作用是指定操作具體的集合(表),這個類是非必須的,它只是指定了泛型的具體型別,也可以在server層呼叫的時候指定

5.建立 UserInfo 實體類

[Table("UserInfo")]
public class UserInfo
{
    /// <summary>
    /// 主鍵
    /// </summary>
    [BsonId]
    public ObjectId Id { get; set; }

    /// <summary>
    /// 使用者名稱
    /// </summary>
    public string Name { get; set; }

    /// <summary>
    /// 年齡
    /// </summary>
    public int Age { get; set; }

    /// <summary>
    /// 建立時間
    /// </summary>
    [BsonDateTimeOptions(Kind = DateTimeKind.Local)]
    public DateTime CreateTime { get; set; }

    /// <summary>
    /// 合作伙伴
    /// </summary>
    public List<Partner> PartnerList { get; set; }

    /// <summary>
    /// 其它資訊
    /// </summary>
    public Info Info { get; set; }
}



public class Partner
{
    /// <summary>
    /// 夥伴名稱
    /// </summary>
    public string Name { get; set; }

    /// <summary>
    /// 合作狀態
    /// </summary>
    public int? Status { get; set; }
}


public class Info 
{
    /// <summary>
    /// 身份編碼
    /// </summary>
    public string Code { get; set; }

    /// <summary>
    /// 圖片
    /// </summary>
    public string Pic { get; set; }
}

mongodb裡預設的主鍵是_id,它會自動生成,型別為ObjectId,強烈推薦使用自動生成,速度快,且能提供獲取對應的時間戳的方法

ObjectId 類似唯一主鍵,可以很快的去生成和排序,包含 12 bytes,含義是:
前4個位元組表示建立 unix 時間戳,格林尼治時間 UTC 時間,比北京時間晚了 8 個小時
接下來的3個位元組是機器標識碼
緊接的兩個位元組由程序 id 組成 PID
最後三個位元組是亂數

時間型別要做對應的處理,標記為當前時間

其它常用註解說明

BsonId修飾的欄位對應BsonDocument中的_id;
BsonDefaultValue(value)用於指定預設值;
BsonIgnore表示不對映,即使BsonDocument中包含該欄位也不會賦值給屬性;
BsonExtraElements修飾的欄位用於儲存沒有對映到類中的其他屬性;
BsonElement可以指定修飾的屬性對映到BsonDocument中的哪個欄位;

使用mongodb的一個主要原因,就是它靈活的儲存方式,類json,我們就來體驗一番,基於這個模型來進行CRUD,我定義的型別如下,基本上能覆蓋99%的使用場景

ObjectId (主鍵)
string (字串)
int (數位)
object (物件)
array (陣列)

我們在BaseRepertoty類裡,實現CRUD,完整程式碼如下

public class BaseRepertoty<T> where T : class, new()
{
    private readonly IMongoDatabase _database;

    private readonly string _collName;

    public BaseRepertoty(BaseDbContext baseDbContext) 
    {
        _database = baseDbContext.MongoDatabase;
        _collName = typeof(T).GetAttributeValue((TableAttribute m) => m.Name);
        _collName = _collName ?? typeof(T).Name;

    }



    #region Add 新增一條資料
    /// <summary>
    /// 新增一條資料
    /// </summary>
    /// <param name="t">新增的實體</param>
    /// <returns></returns>
    public bool Add(T t)
    {
        try
        {
            var client = _database.GetCollection<T>(_collName);
            client.InsertOne(t);
            return true;
        }
        catch (Exception ex)
        {
            return false;
        }
    }
    #endregion

    #region AddAsync 非同步新增一條資料
    /// <summary>
    /// 非同步新增一條資料
    /// </summary>
    /// <param name="t">新增的實體</param>
    /// <returns></returns>
    public async Task<bool> AddAsync(T t)
    {
        try
        {
            var client = _database.GetCollection<T>(_collName);
            await client.InsertOneAsync(t);
            return true;
        }
        catch
        {
            return false;
        }
    }
    #endregion

    #region InsertMany 批次插入
    /// <summary>
    /// 批次插入
    /// </summary>
    /// <param name="t">實體集合</param>
    /// <returns></returns>
    public bool InsertMany(List<T> t)
    {
        try
        {
            var client = _database.GetCollection<T>(_collName);
            client.InsertMany(t);
            return true;
        }
        catch (Exception ex)
        {
            return false;
        }
    }
    #endregion

    #region InsertManyAsync 非同步批次插入
    /// <summary>
    /// 非同步批次插入
    /// </summary>
    /// <param name="t">實體集合</param>
    /// <returns></returns>
    public async Task<bool> InsertManyAsync(List<T> t)
    {
        try
        {
            var client = _database.GetCollection<T>(_collName);
            await client.InsertManyAsync(t);
            return true;
        }
        catch
        {
            return false;
        }
    }
    #endregion

    #region UpdateOne 修改資料(單條)
    /// <summary>
    /// 批次修改資料
    /// </summary>
    /// <param name="update">要修改的欄位</param>
    /// <param name="filter">修改條件</param>
    /// <returns></returns>
    public UpdateResult UpdateOne(UpdateDefinition<T> update, FilterDefinition<T> filter)
    {
        try
        {
            var client = _database.GetCollection<T>(_collName);
            return client.UpdateOne(filter, update);
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
    #endregion

    #region UpdateOneAsync 非同步批次修改資料
    /// <summary>
    /// 非同步批次修改資料
    /// </summary>
    /// <param name="update">要修改的欄位</param>
    /// <param name="filter">修改條件</param>
    /// <returns></returns>
    public async Task<UpdateResult> UpdateOneAsync(UpdateDefinition<T> update, FilterDefinition<T> filter)
    {
        try
        {
            var client = _database.GetCollection<T>(_collName);
            return await client.UpdateOneAsync(filter, update);
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
    #endregion

    #region UpdateManay 批次修改資料
    /// <summary>
    /// 批次修改資料
    /// </summary>
    /// <param name="update">要修改的欄位</param>
    /// <param name="filter">修改條件</param>
    /// <returns></returns>
    public UpdateResult UpdateManay(UpdateDefinition<T> update, FilterDefinition<T> filter)
    {
        try
        {
            var client = _database.GetCollection<T>(_collName);
            return  client.UpdateMany(filter, update);
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
    #endregion

    #region UpdateManayAsync 非同步批次修改資料
    /// <summary>
    /// 非同步批次修改資料
    /// </summary>
    /// <param name="update">要修改的欄位</param>
    /// <param name="filter">修改條件</param>
    /// <returns></returns>
    public async Task<UpdateResult> UpdateManayAsync(UpdateDefinition<T> update, FilterDefinition<T> filter)
    {
        try
        {
            var client = _database.GetCollection<T>(_collName);
            return await client.UpdateManyAsync(filter, update);
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
    #endregion



    #region DeleteOne 刪除一條資料
    /// <summary>
    /// 刪除多條資料
    /// </summary>
    /// <param name="filter">刪除的條件</param>
    /// <returns></returns>
    public DeleteResult DeleteOne(FilterDefinition<T> filter)
    {
        try
        {
            var client = _database.GetCollection<T>(_collName);
            return client.DeleteOne(filter);
        }
        catch (Exception ex)
        {
            throw ex;
        }

    }
    #endregion

    #region DeleteOneAsync 非同步刪除一條資料
    /// <summary>
    /// 非同步刪除多條資料
    /// </summary>
    /// <param name="filter">刪除的條件</param>
    /// <returns></returns>
    public async Task<DeleteResult> DeleteOneAsync(FilterDefinition<T> filter)
    {
        try
        {
            var client = _database.GetCollection<T>(_collName);
            return await client.DeleteOneAsync(filter);
        }
        catch (Exception ex)
        {
            throw ex;
        }

    }
    #endregion

    #region DeleteMany 刪除多條資料
    /// <summary>
    /// 刪除多條資料
    /// </summary>
    /// <param name="filter">刪除的條件</param>
    /// <returns></returns>
    public DeleteResult DeleteMany(FilterDefinition<T> filter)
    {
        try
        {
            var client = _database.GetCollection<T>(_collName);
            return client.DeleteMany(filter);
        }
        catch (Exception ex)
        {
            throw ex;
        }

    }
    #endregion

    #region DeleteManyAsync 非同步刪除多條資料
    /// <summary>
    /// 非同步刪除多條資料
    /// </summary>
    /// <param name="filter">刪除的條件</param>
    /// <returns></returns>
    public async Task<DeleteResult> DeleteManyAsync(FilterDefinition<T> filter)
    {
        try
        {
            var client = _database.GetCollection<T>(_collName);
            return await client.DeleteManyAsync(filter);
        }
        catch (Exception ex)
        {
            throw ex;
        }

    }
    #endregion

    #region FindOne 根據id查詢一條資料
    /// <summary>
    /// 根據id查詢一條資料
    /// </summary>
    /// <param name="id">objectid</param>
    /// <param name="field">要查詢的欄位,不寫時查詢全部</param>
    /// <returns></returns>
    public T FindOne(string id, bool isObjectId = true, string[] field = null)
    {
        try
        {
            var client = _database.GetCollection<T>(_collName);
            FilterDefinition<T> filter;
            if (isObjectId)
            {
                filter = Builders<T>.Filter.Eq("_id", new ObjectId(id));
            }
            else
            {
                filter = Builders<T>.Filter.Eq("_id", id);
            }
            //不指定查詢欄位
            if (field == null || field.Length == 0)
            {
                return client.Find(filter).FirstOrDefault<T>();
            }

            //制定查詢欄位
            var fieldList = new List<ProjectionDefinition<T>>();
            for (int i = 0; i < field.Length; i++)
            {
                fieldList.Add(Builders<T>.Projection.Include(field[i].ToString()));
            }
            var projection = Builders<T>.Projection.Combine(fieldList);
            fieldList?.Clear();
            return client.Find(filter).Project<T>(projection).FirstOrDefault<T>();
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
    #endregion

    #region FindOneAsync 非同步根據id查詢一條資料
    /// <summary>
    /// 非同步根據id查詢一條資料
    /// </summary>
    /// <param name="id">objectid</param>
    /// <returns></returns>
    public async Task<T> FindOneAsync(string id, bool isObjectId = true, string[] field = null)
    {
        try
        {
            var client = _database.GetCollection<T>(_collName);
            FilterDefinition<T> filter;
            if (isObjectId)
            {
                filter = Builders<T>.Filter.Eq("_id", new ObjectId(id));
            }
            else
            {
                filter = Builders<T>.Filter.Eq("_id", id);
            }

            //不指定查詢欄位
            if (field == null || field.Length == 0)
            {
                return await client.Find(filter).FirstOrDefaultAsync();
            }

            //制定查詢欄位
            var fieldList = new List<ProjectionDefinition<T>>();
            for (int i = 0; i < field.Length; i++)
            {
                fieldList.Add(Builders<T>.Projection.Include(field[i].ToString()));
            }
            var projection = Builders<T>.Projection.Combine(fieldList);
            fieldList?.Clear();
            return await client.Find(filter).Project<T>(projection).FirstOrDefaultAsync();
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
    #endregion

    #region FindList 查詢集合
    /// <summary>
    /// 查詢集合
    /// </summary>
    /// <param name="filter">查詢條件</param>
    /// <param name="field">要查詢的欄位,不寫時查詢全部</param>
    /// <param name="sort">要排序的欄位</param>
    /// <returns></returns>
    public List<T> FindList(FilterDefinition<T> filter, string[] field = null, SortDefinition<T> sort = null)
    {
        try
        {
            var client = _database.GetCollection<T>(_collName);
            //不指定查詢欄位
            if (field == null || field.Length == 0)
            {
                if (sort == null) return client.Find(filter).ToList();
                //進行排序
                return client.Find(filter).Sort(sort).ToList();
            }

            //制定查詢欄位
            var fieldList = new List<ProjectionDefinition<T>>();
            for (int i = 0; i < field.Length; i++)
            {
                fieldList.Add(Builders<T>.Projection.Include(field[i].ToString()));
            }
            var projection = Builders<T>.Projection.Combine(fieldList);
            fieldList?.Clear();
            if (sort == null) return client.Find(filter).Project<T>(projection).ToList();
            //排序查詢
            return client.Find(filter).Sort(sort).Project<T>(projection).ToList();
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
    #endregion

    #region FindListAsync 非同步查詢集合
    /// <summary>
    /// 非同步查詢集合
    /// </summary>
    /// <param name="filter">查詢條件</param>
    /// <param name="field">要查詢的欄位,不寫時查詢全部</param>
    /// <param name="sort">要排序的欄位</param>
    /// <returns></returns>
    public async Task<List<T>> FindListAsync(FilterDefinition<T> filter, string[] field = null, SortDefinition<T> sort = null)
    {
        try
        {
            var client = _database.GetCollection<T>(_collName);
            //不指定查詢欄位
            if (field == null || field.Length == 0)
            {
                //return await client.Find(new BsonDocument()).ToListAsync();
                if (sort == null) return await client.Find(filter).ToListAsync();
                return await client.Find(filter).Sort(sort).ToListAsync();
            }

            //制定查詢欄位
            var fieldList = new List<ProjectionDefinition<T>>();
            for (int i = 0; i < field.Length; i++)
            {
                fieldList.Add(Builders<T>.Projection.Include(field[i].ToString()));
            }
            var projection = Builders<T>.Projection.Combine(fieldList);
            fieldList?.Clear();
            if (sort == null) return await client.Find(filter).Project<T>(projection).ToListAsync();
            //排序查詢
            return await client.Find(filter).Sort(sort).Project<T>(projection).ToListAsync();
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
    #endregion

    #region FindListByPage 分頁查詢集合
    /// <summary>
    /// 分頁查詢集合
    /// </summary>
    /// <param name="filter">查詢條件</param>
    /// <param name="pageIndex">當前頁</param>
    /// <param name="pageSize">頁容量</param>
    /// <param name="count">總條數</param>
    /// <param name="field">要查詢的欄位,不寫時查詢全部</param>
    /// <param name="sort">要排序的欄位</param>
    /// <returns></returns>
    public List<T> FindListByPage(FilterDefinition<T> filter, int pageIndex, int pageSize, out long count, string[] field = null, SortDefinition<T> sort = null)
    {
        try
        {
            var client = _database.GetCollection<T>(_collName);
            count = client.CountDocuments(filter);
            //不指定查詢欄位
            if (field == null || field.Length == 0)
            {
                if (sort == null) return client.Find(filter).Skip((pageIndex - 1) * pageSize).Limit(pageSize).ToList();
                //進行排序
                return client.Find(filter).Sort(sort).Skip((pageIndex - 1) * pageSize).Limit(pageSize).ToList();
            }

            //制定查詢欄位
            var fieldList = new List<ProjectionDefinition<T>>();
            for (int i = 0; i < field.Length; i++)
            {
                fieldList.Add(Builders<T>.Projection.Include(field[i].ToString()));
            }
            var projection = Builders<T>.Projection.Combine(fieldList);
            fieldList?.Clear();

            //不排序
            if (sort == null) return client.Find(filter).Project<T>(projection).Skip((pageIndex - 1) * pageSize).Limit(pageSize).ToList();

            //排序查詢
            return client.Find(filter).Sort(sort).Project<T>(projection).Skip((pageIndex - 1) * pageSize).Limit(pageSize).ToList();

        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
    #endregion

    #region FindListByPageAsync 非同步分頁查詢集合
    /// <summary>
    /// 非同步分頁查詢集合
    /// </summary>
    /// <param name="filter">查詢條件</param>
    /// <param name="pageIndex">當前頁</param>
    /// <param name="pageSize">頁容量</param>
    /// <param name="field">要查詢的欄位,不寫時查詢全部</param>
    /// <param name="sort">要排序的欄位</param>
    /// <returns></returns>
    public async Task<List<T>> FindListByPageAsync(FilterDefinition<T> filter, int pageIndex, int pageSize, string[] field = null, SortDefinition<T> sort = null)
    {
        try
        {
            var client = _database.GetCollection<T>(_collName);
            //不指定查詢欄位
            if (field == null || field.Length == 0)
            {
                if (sort == null) return await client.Find(filter).Skip((pageIndex - 1) * pageSize).Limit(pageSize).ToListAsync();
                //進行排序
                return await client.Find(filter).Sort(sort).Skip((pageIndex - 1) * pageSize).Limit(pageSize).ToListAsync();
            }

            //制定查詢欄位
            var fieldList = new List<ProjectionDefinition<T>>();
            for (int i = 0; i < field.Length; i++)
            {
                fieldList.Add(Builders<T>.Projection.Include(field[i].ToString()));
            }
            var projection = Builders<T>.Projection.Combine(fieldList);
            fieldList?.Clear();

            //不排序
            if (sort == null) return await client.Find(filter).Project<T>(projection).Skip((pageIndex - 1) * pageSize).Limit(pageSize).ToListAsync();

            //排序查詢
            return await client.Find(filter).Sort(sort).Project<T>(projection).Skip((pageIndex - 1) * pageSize).Limit(pageSize).ToListAsync();

        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
    #endregion


    #region Count 根據條件獲取總數
    /// <summary>
    /// 根據條件獲取總數
    /// </summary>
    /// <param name="filter">條件</param>
    /// <returns></returns>
    public long Count(FilterDefinition<T> filter)
    {
        try
        {
            var client = _database.GetCollection<T>(_collName);
            return client.CountDocuments(filter);
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
    #endregion

    #region CountAsync 非同步根據條件獲取總數
    /// <summary>
    /// 非同步根據條件獲取總數
    /// </summary>
    /// <param name="filter">條件</param>
    /// <returns></returns>
    public async Task<long> CountAsync(FilterDefinition<T> filter)
    {
        try
        {
            var client = _database.GetCollection<T>(_collName);
            return await client.CountDocumentsAsync(filter);
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
    #endregion
}

6.建立 UserInfoService 類

public class UserInfoService
{
    private readonly UserInfoRepertoty _userInfoRepertoty;

    private readonly FilterDefinitionBuilder<UserInfo> _buildFilter;
    public UserInfoService(UserInfoRepertoty userInfoRepertoty) 
    {
        _userInfoRepertoty = userInfoRepertoty;
        _buildFilter = Builders<UserInfo>.Filter;
    }
}

體驗mongodb獨特的使用方式,這裡挑出兩個具有代表性的操作進行講解,測試資料

分頁查詢集合(表)

  • 1.動態條件查詢
  • 2.查詢檔案指定欄位
  • 3.排序
  • 4.分頁

定義查詢操作

FilterDefinition<UserInfo> filter = _buildFilter.Empty;

查詢條件由查詢條件構造器構建,這個地方網上很多範例寫的有bug,當查詢所有集合(表)資料的時候,filter = null 在轉換的時候會丟擲異常

//建立查詢條件構造器
FilterDefinitionBuilder<UserInfo> _buildFilter = Builders<UserInfo>.Filter;
//定義查詢條件
FilterDefinition<UserInfo> filter = null;
if(!string.IsNullOrEmpty(request.Name)) filter = _buildFilter.Eq(m => m.Name, request.Name);

這裡有很多種型別的構造器,對應不同的操作

//排序操作
SortDefinition<UserInfo> sort
//排序構造器
Builders<UserInfo>.Sort

修改操作
UpdateDefinition<UserInfo> update
//修改構造器
Builders<UserInfo>.Update

完整的查詢範例,比較麻煩的地方,是針對陣列的條件查詢,如果巢狀的層數比較多,查詢也是同理的套娃查詢

public class GetUserListRequest
{
    /// <summary>
    /// 名稱
    /// </summary>
    public string Name { get; set; }

    /// <summary>
    /// 年齡
    /// </summary>
    public int? Age { get; set; }


    /// <summary>
    /// 建立時間
    /// </summary>
    public DateTime CreateTime { get; set; }

    /// <summary>
    /// 合作伙伴
    /// </summary>
    public Partner PartnerList { get; set; }

    /// <summary>
    /// 資訊
    /// </summary>
    public Info Info { get; set; }
}

public async Task<List<UserInfo>> GetUserPageList(GetUserListRequest request)
{
    if (request == null) return new List<UserInfo>();
    FilterDefinition<UserInfo> filter = _buildFilter.Empty;

    SortDefinition<UserInfo> sort = Builders<UserInfo>.Sort.Ascending(m => m.Age);

    if (!string.IsNullOrEmpty(request.Name))
    {
        filter = _buildFilter.Eq(m => m.Name, request.Name);
    }
    if (request.Age.HasValue)
    {
        filter = _buildFilter.Eq(m => m.Age, request.Age);
    }
    if (request.PartnerList != null)
    {
        if (request.PartnerList.Status.HasValue)
        {
            filter = _buildFilter.ElemMatch("PartnerList", Builders<Partner>.Filter.Eq(m => m.Status, request.PartnerList.Status));
        }
    }
    if (request.Info != null)
    {
        if (!string.IsNullOrEmpty(request.Info.Code))
        {
            filter = _buildFilter.Eq(m => m.Info.Code, request.Info.Code);
        }
    }
    var list = await _userInfoRepertoty.FindListByPageAsync(filter,1,3, new string[] { "Name","Age", "CreateTime" }, sort);
    return list;
}

動態條件查詢(查詢全部)

var list = await _userInfoRepertoty.FindListByPageAsync(filter, 1, 30);

條件查詢,排序,分頁,查詢指定欄位

var list = await _userInfoRepertoty.FindListByPageAsync(filter,1,3, new string[] { "Name","Age", "CreateTime" }, sort);


除了使用物件模型進行操作,也可以直接使用mongodb原生的BsonDocument進行操作

var buildFilter = Builders<BsonDocument>.Filter;
FilterDefinition<BsonDocument> filter = _buildFilter.Empty;;
BsonDocument bson = new BsonDocument
{
    { "Age",20},
    {"Info.Status",3 }
};

foreach (var bs in bson)
{
    filter = _buildFilter.Eq(bs.Name, bs.Value);

}
var sort = Builders<BsonDocument>.Sort;
var list = await collection.Find(filter).Sort(sort.Descending("age")).ToListAsync();

修改集合(表)的資料

  • 1.修改滿足條件的檔案
  • 2.修改檔案的部分欄位
public async Task UpdateUserInfo()
{
    //修改條件
    FilterDefinition<UserInfo> filter = _buildFilter.Empty;
    filter = _buildFilter.Eq(m => m.Name, "tibos");
    filter = _buildFilter.ElemMatch(list => list.PartnerList, child => child.Status == 1);


    //修改欄位
    var update = Builders<UserInfo>.Update.Set("Age",100).Set("PartnerList.$.Name", "ppp").Set("PartnerList.$.Status", "");
    await _userInfoRepertoty.UpdateManayAsync(update, filter);
}