王广跃 發表於 2023-1-7 17:36:00

.net core操作MongoDB

<h2 id="前言">前言</h2>
<p>现实中认识的一个搞java(<s>百万富婆</s>)的大佬,已经转行做抖音主播了,搞技术的只能赶在年前再水一篇博客,不足之处欢迎拍砖,以免误人子弟,呔,真是太难受了<br>
<img src="https://img2023.cnblogs.com/blog/772322/202301/772322-20230107170752864-1644844153.jpg" alt="image" loading="lazy"></p>
<h2 id="环境准备">环境准备</h2>
<blockquote>
<ul>
<li>.net core 3.1</li>
<li>MongoDB</li>
<li>Navicat Premium 16</li>
</ul>
</blockquote>
<h3 id="创建项目">创建项目</h3>
<blockquote>
<p>1.选择ASP.NET Core Web API 项目模板</p>
</blockquote>
<p><img src="https://img2023.cnblogs.com/blog/772322/202301/772322-20230107162958530-406321051.png" alt="image" loading="lazy"></p>
<blockquote>
<p>2.配置项目信息 项目名称,项目路径</p>
</blockquote>
<p><img src="https://img2023.cnblogs.com/blog/772322/202301/772322-20230107163011158-173823834.png" alt="image" loading="lazy"></p>
<blockquote>
<p>3.配置项目其它信息,这里选择使用.net core 3.1 不配置https</p>
</blockquote>
<p><img src="https://img2023.cnblogs.com/blog/772322/202301/772322-20230107163038480-1022864056.png" alt="image" loading="lazy"></p>
<h3 id="添加依赖">添加依赖</h3>
<blockquote>
<p>1.获取MongoDB.Driver包 版本 2.18.0<br></p>
</blockquote>
<pre><code>方案A. install-package MongoDB.Driver
方案B. nuget包管理工具搜索 MongoDB.Driver
方案C. 选中项目,双击,添加
&lt;ItemGroup&gt;
    &lt;PackageReference Include="MongoDB.Driver" Version="2.18.0" /&gt;
&lt;/ItemGroup&gt;
</code></pre>
<h3 id="注册中间件">注册中间件</h3>
<blockquote>
<p>1.添加配置文件</p>
</blockquote>
<pre><code class="language-json">"MongoDB": {
"ConnName": "mongodb://root:123456@127.0.0.1:27017/",
"DatabaseName": "test"
}
</code></pre>
<blockquote>
<p>2.添加配置类</p>
</blockquote>
<pre><code>public class MongoDBConfig
{
    /// &lt;summary&gt;
    /// 连接字符串
    /// &lt;/summary&gt;
    public string ConnName { get; set; }

    /// &lt;summary&gt;
    /// 数据库名称
    /// &lt;/summary&gt;
    public string DatabaseName { get; set; }
}
</code></pre>
<blockquote>
<p>3.注册配置文件与中间件</p>
</blockquote>
<pre><code>//读取配置文件
var mongoDBOptions = Configuration.GetSection("MongoDB").Get&lt;MongoDBConfig&gt;();

//注册配置
services.Configure&lt;MongoDBConfig&gt;(this.Configuration.GetSection("MongoDB"));

//注册中间件
services.AddSingleton(new MongoClient(mongoDBOptions.ConnName));
</code></pre>
<p>其实就是注册了一个mongodb的客户端实例,然后用这个客户端实例来实现crud,如果你想优雅点(<s>强迫症</s>),也可以自定义一个拓展,来注册这个实例,这是一个通用技巧,后面使用到的类请<strong><font color="red" size="3">自行注册</font></strong></p>
<pre><code>public static class MongoDBExtensions
{
    public static void AddMongoDB(this IServiceCollection services, Action&lt;MongoDBConfig&gt; setupAction)
    {
      if (setupAction == null)
      {
            throw new ArgumentNullException(nameof(setupAction));
      }
      var options = new MongoDBConfig();
      setupAction(options);
      services.Configure(setupAction);
      services.AddSingleton(new MongoClient(options.ConnName));
    }
}
</code></pre>
<p>使用拓展,来注册中间件</p>
<pre><code>var mongoDBOptions = Configuration.GetSection("MongoDB").Get&lt;MongoDBConfig&gt;();
services.AddMongoDB(m =&gt;
{
    m.ConnName = mongoDBOptions.ConnName;
    m.DatabaseName = mongoDBOptions.DatabaseName;
});
</code></pre>
<h3 id="封装基础操作">封装基础操作</h3>
<p>最常用的办法,就是弄个DBHelper类,这种简单粗暴的方式,在.net core里使用并不优雅(<s>网上教程太多了,不想重复的水</s>),这里模拟常规的仓储模式,进行演示</p>
<blockquote>
<p>1.创建 Service,Repertoty,Model 文件夹<br>
2.创建 BaseDbContext 类</p>
</blockquote>
<pre><code>public class BaseDbContext
{
    private readonly IMongoDatabase _database;
    public BaseDbContext(MongoClient client, IOptions&lt;MongoDBConfig&gt; options)
    {
      //决定使用哪个库
      _database = client.GetDatabase(options.Value.DatabaseName);
    }

    /// &lt;summary&gt;
    /// 数据库对象
    /// &lt;/summary&gt;
    public IMongoDatabase MongoDatabase { get{ return _database; } }
}
</code></pre>
<p>如果项目只操作一个数据库,直接在基类里指定操作的数据库即可,如果需要操作多个数据库,可以再新建一个子类(TestDbContext),在子类里指定要操作的数据库<br>
前面我已经注册了mongodb的客户端跟配置文件,所以在Startup类下,可以直接注册这个类,容器会自动管理这些依赖</p>
<pre><code>services.AddSingleton(typeof(BaseDbContext));
</code></pre>
<p>如果你想更优雅点(<s>强迫症</s>),可以创建一个IBaseDbContext 接口,在接口里定义相关的规范</p>
<pre><code>services.AddSingleton&lt;IBaseDbContext&gt;();
</code></pre>
<blockquote>
<p>3.创建 BaseRepertoty 类</p>
</blockquote>
<pre><code>public class BaseRepertoty&lt;T&gt; 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) =&gt; m.Name);
      _collName = _collName ?? typeof(T).Name;

    }
}
</code></pre>
<p>前面我们已经注册了BaseDbContext,它的主要作用是确定操作的库,那BaseRepertoty就是对具体集合(表)的操作,这里使用泛型,避免重复的CRUD操作<br>
我新建了一个拓展,用于获取实体类上真实集合(表)的名称,如果用户没有指定,则取实体类的类名,做为集合(表)的名称</p>
<pre><code>public static class AttributeExtensions
{
    public static TValue GetAttributeValue&lt;TAttribute, TValue&gt;(
      this Type type,
      Func&lt;TAttribute, TValue&gt; valueSelector)
      where TAttribute : Attribute
    {
      var att = type.GetCustomAttributes(
            typeof(TAttribute), true
      ).FirstOrDefault() as TAttribute;
      if (att != null)
      {
            return valueSelector(att);
      }
      return default(TValue);
    }
}
</code></pre>
<blockquote>
<p>4.创建 UserInfoRepertoty 类</p>
</blockquote>
<pre><code>public class UserInfoRepertoty : BaseRepertoty&lt;UserInfo&gt;
{
    public UserInfoRepertoty(BaseDbContext baseDbContext) : base(baseDbContext)
    {

    }
}
</code></pre>
<p>它的作用是指定操作具体的集合(表),这个类是非必须的,它只是指定了泛型的具体类型,也可以在server层调用的时候指定</p>
<blockquote>
<p>5.创建 UserInfo 实体类</p>
</blockquote>
<pre><code>
public class UserInfo
{
    /// &lt;summary&gt;
    /// 主键
    /// &lt;/summary&gt;
   
    public ObjectId Id { get; set; }

    /// &lt;summary&gt;
    /// 用户名
    /// &lt;/summary&gt;
    public string Name { get; set; }

    /// &lt;summary&gt;
    /// 年龄
    /// &lt;/summary&gt;
    public int Age { get; set; }

    /// &lt;summary&gt;
    /// 创建时间
    /// &lt;/summary&gt;
   
    public DateTime CreateTime { get; set; }

    /// &lt;summary&gt;
    /// 合作伙伴
    /// &lt;/summary&gt;
    public List&lt;Partner&gt; PartnerList { get; set; }

    /// &lt;summary&gt;
    /// 其它信息
    /// &lt;/summary&gt;
    public Info Info { get; set; }
}



public class Partner
{
    /// &lt;summary&gt;
    /// 伙伴名称
    /// &lt;/summary&gt;
    public string Name { get; set; }

    /// &lt;summary&gt;
    /// 合作状态
    /// &lt;/summary&gt;
    public int? Status { get; set; }
}


public class Info
{
    /// &lt;summary&gt;
    /// 身份编码
    /// &lt;/summary&gt;
    public string Code { get; set; }

    /// &lt;summary&gt;
    /// 图片
    /// &lt;/summary&gt;
    public string Pic { get; set; }
}
</code></pre>
<p>mongodb里默认的主键是_id,它会自动生成,类型为ObjectId,强烈推荐使用自动生成,速度快,且能提供获取对应的时间戳的方法</p>
<pre><code>ObjectId 类似唯一主键,可以很快的去生成和排序,包含 12 bytes,含义是:
前4个字节表示创建 unix 时间戳,格林尼治时间 UTC 时间,比北京时间晚了 8 个小时
接下来的3个字节是机器标识码
紧接的两个字节由进程 id 组成 PID
最后三个字节是随机数
</code></pre>
<p>时间类型要做对应的处理,标记为当前时间</p>
<p>其它常用注解说明</p>
<pre><code>BsonId修饰的字段对应BsonDocument中的_id;
BsonDefaultValue(value)用于指定默认值;
BsonIgnore表示不映射,即使BsonDocument中包含该字段也不会赋值给属性;
BsonExtraElements修饰的字段用于存储没有映射到类中的其他属性;
BsonElement可以指定修饰的属性映射到BsonDocument中的哪个字段;
</code></pre>
<p>使用mongodb的一个主要原因,就是它灵活的存储方式,类json,我们就来体验一番,基于这个模型来进行CRUD,我定义的类型如下,基本上能覆盖99%的使用场景</p>
<p>ObjectId    (主键)<br>
string      (字符串)<br>
int         (数字)<br>
object      (对象)<br>
array       (数组)</p>
<p>我们在BaseRepertoty类里,实现CRUD,完整代码如下</p>
<pre><code>public class BaseRepertoty&lt;T&gt; 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) =&gt; m.Name);
      _collName = _collName ?? typeof(T).Name;

    }



    #region Add 添加一条数据
    /// &lt;summary&gt;
    /// 添加一条数据
    /// &lt;/summary&gt;
    /// &lt;param name="t"&gt;添加的实体&lt;/param&gt;
    /// &lt;returns&gt;&lt;/returns&gt;
    public bool Add(T t)
    {
      try
      {
            var client = _database.GetCollection&lt;T&gt;(_collName);
            client.InsertOne(t);
            return true;
      }
      catch (Exception ex)
      {
            return false;
      }
    }
    #endregion

    #region AddAsync 异步添加一条数据
    /// &lt;summary&gt;
    /// 异步添加一条数据
    /// &lt;/summary&gt;
    /// &lt;param name="t"&gt;添加的实体&lt;/param&gt;
    /// &lt;returns&gt;&lt;/returns&gt;
    public async Task&lt;bool&gt; AddAsync(T t)
    {
      try
      {
            var client = _database.GetCollection&lt;T&gt;(_collName);
            await client.InsertOneAsync(t);
            return true;
      }
      catch
      {
            return false;
      }
    }
    #endregion

    #region InsertMany 批量插入
    /// &lt;summary&gt;
    /// 批量插入
    /// &lt;/summary&gt;
    /// &lt;param name="t"&gt;实体集合&lt;/param&gt;
    /// &lt;returns&gt;&lt;/returns&gt;
    public bool InsertMany(List&lt;T&gt; t)
    {
      try
      {
            var client = _database.GetCollection&lt;T&gt;(_collName);
            client.InsertMany(t);
            return true;
      }
      catch (Exception ex)
      {
            return false;
      }
    }
    #endregion

    #region InsertManyAsync 异步批量插入
    /// &lt;summary&gt;
    /// 异步批量插入
    /// &lt;/summary&gt;
    /// &lt;param name="t"&gt;实体集合&lt;/param&gt;
    /// &lt;returns&gt;&lt;/returns&gt;
    public async Task&lt;bool&gt; InsertManyAsync(List&lt;T&gt; t)
    {
      try
      {
            var client = _database.GetCollection&lt;T&gt;(_collName);
            await client.InsertManyAsync(t);
            return true;
      }
      catch
      {
            return false;
      }
    }
    #endregion

    #region UpdateOne 修改数据(单条)
    /// &lt;summary&gt;
    /// 批量修改数据
    /// &lt;/summary&gt;
    /// &lt;param name="update"&gt;要修改的字段&lt;/param&gt;
    /// &lt;param name="filter"&gt;修改条件&lt;/param&gt;
    /// &lt;returns&gt;&lt;/returns&gt;
    public UpdateResult UpdateOne(UpdateDefinition&lt;T&gt; update, FilterDefinition&lt;T&gt; filter)
    {
      try
      {
            var client = _database.GetCollection&lt;T&gt;(_collName);
            return client.UpdateOne(filter, update);
      }
      catch (Exception ex)
      {
            throw ex;
      }
    }
    #endregion

    #region UpdateOneAsync 异步批量修改数据
    /// &lt;summary&gt;
    /// 异步批量修改数据
    /// &lt;/summary&gt;
    /// &lt;param name="update"&gt;要修改的字段&lt;/param&gt;
    /// &lt;param name="filter"&gt;修改条件&lt;/param&gt;
    /// &lt;returns&gt;&lt;/returns&gt;
    public async Task&lt;UpdateResult&gt; UpdateOneAsync(UpdateDefinition&lt;T&gt; update, FilterDefinition&lt;T&gt; filter)
    {
      try
      {
            var client = _database.GetCollection&lt;T&gt;(_collName);
            return await client.UpdateOneAsync(filter, update);
      }
      catch (Exception ex)
      {
            throw ex;
      }
    }
    #endregion

    #region UpdateManay 批量修改数据
    /// &lt;summary&gt;
    /// 批量修改数据
    /// &lt;/summary&gt;
    /// &lt;param name="update"&gt;要修改的字段&lt;/param&gt;
    /// &lt;param name="filter"&gt;修改条件&lt;/param&gt;
    /// &lt;returns&gt;&lt;/returns&gt;
    public UpdateResult UpdateManay(UpdateDefinition&lt;T&gt; update, FilterDefinition&lt;T&gt; filter)
    {
      try
      {
            var client = _database.GetCollection&lt;T&gt;(_collName);
            returnclient.UpdateMany(filter, update);
      }
      catch (Exception ex)
      {
            throw ex;
      }
    }
    #endregion

    #region UpdateManayAsync 异步批量修改数据
    /// &lt;summary&gt;
    /// 异步批量修改数据
    /// &lt;/summary&gt;
    /// &lt;param name="update"&gt;要修改的字段&lt;/param&gt;
    /// &lt;param name="filter"&gt;修改条件&lt;/param&gt;
    /// &lt;returns&gt;&lt;/returns&gt;
    public async Task&lt;UpdateResult&gt; UpdateManayAsync(UpdateDefinition&lt;T&gt; update, FilterDefinition&lt;T&gt; filter)
    {
      try
      {
            var client = _database.GetCollection&lt;T&gt;(_collName);
            return await client.UpdateManyAsync(filter, update);
      }
      catch (Exception ex)
      {
            throw ex;
      }
    }
    #endregion



    #region DeleteOne 删除一条数据
    /// &lt;summary&gt;
    /// 删除多条数据
    /// &lt;/summary&gt;
    /// &lt;param name="filter"&gt;删除的条件&lt;/param&gt;
    /// &lt;returns&gt;&lt;/returns&gt;
    public DeleteResult DeleteOne(FilterDefinition&lt;T&gt; filter)
    {
      try
      {
            var client = _database.GetCollection&lt;T&gt;(_collName);
            return client.DeleteOne(filter);
      }
      catch (Exception ex)
      {
            throw ex;
      }

    }
    #endregion

    #region DeleteOneAsync 异步删除一条数据
    /// &lt;summary&gt;
    /// 异步删除多条数据
    /// &lt;/summary&gt;
    /// &lt;param name="filter"&gt;删除的条件&lt;/param&gt;
    /// &lt;returns&gt;&lt;/returns&gt;
    public async Task&lt;DeleteResult&gt; DeleteOneAsync(FilterDefinition&lt;T&gt; filter)
    {
      try
      {
            var client = _database.GetCollection&lt;T&gt;(_collName);
            return await client.DeleteOneAsync(filter);
      }
      catch (Exception ex)
      {
            throw ex;
      }

    }
    #endregion

    #region DeleteMany 删除多条数据
    /// &lt;summary&gt;
    /// 删除多条数据
    /// &lt;/summary&gt;
    /// &lt;param name="filter"&gt;删除的条件&lt;/param&gt;
    /// &lt;returns&gt;&lt;/returns&gt;
    public DeleteResult DeleteMany(FilterDefinition&lt;T&gt; filter)
    {
      try
      {
            var client = _database.GetCollection&lt;T&gt;(_collName);
            return client.DeleteMany(filter);
      }
      catch (Exception ex)
      {
            throw ex;
      }

    }
    #endregion

    #region DeleteManyAsync 异步删除多条数据
    /// &lt;summary&gt;
    /// 异步删除多条数据
    /// &lt;/summary&gt;
    /// &lt;param name="filter"&gt;删除的条件&lt;/param&gt;
    /// &lt;returns&gt;&lt;/returns&gt;
    public async Task&lt;DeleteResult&gt; DeleteManyAsync(FilterDefinition&lt;T&gt; filter)
    {
      try
      {
            var client = _database.GetCollection&lt;T&gt;(_collName);
            return await client.DeleteManyAsync(filter);
      }
      catch (Exception ex)
      {
            throw ex;
      }

    }
    #endregion

    #region FindOne 根据id查询一条数据
    /// &lt;summary&gt;
    /// 根据id查询一条数据
    /// &lt;/summary&gt;
    /// &lt;param name="id"&gt;objectid&lt;/param&gt;
    /// &lt;param name="field"&gt;要查询的字段,不写时查询全部&lt;/param&gt;
    /// &lt;returns&gt;&lt;/returns&gt;
    public T FindOne(string id, bool isObjectId = true, string[] field = null)
    {
      try
      {
            var client = _database.GetCollection&lt;T&gt;(_collName);
            FilterDefinition&lt;T&gt; filter;
            if (isObjectId)
            {
                filter = Builders&lt;T&gt;.Filter.Eq("_id", new ObjectId(id));
            }
            else
            {
                filter = Builders&lt;T&gt;.Filter.Eq("_id", id);
            }
            //不指定查询字段
            if (field == null || field.Length == 0)
            {
                return client.Find(filter).FirstOrDefault&lt;T&gt;();
            }

            //制定查询字段
            var fieldList = new List&lt;ProjectionDefinition&lt;T&gt;&gt;();
            for (int i = 0; i &lt; field.Length; i++)
            {
                fieldList.Add(Builders&lt;T&gt;.Projection.Include(field.ToString()));
            }
            var projection = Builders&lt;T&gt;.Projection.Combine(fieldList);
            fieldList?.Clear();
            return client.Find(filter).Project&lt;T&gt;(projection).FirstOrDefault&lt;T&gt;();
      }
      catch (Exception ex)
      {
            throw ex;
      }
    }
    #endregion

    #region FindOneAsync 异步根据id查询一条数据
    /// &lt;summary&gt;
    /// 异步根据id查询一条数据
    /// &lt;/summary&gt;
    /// &lt;param name="id"&gt;objectid&lt;/param&gt;
    /// &lt;returns&gt;&lt;/returns&gt;
    public async Task&lt;T&gt; FindOneAsync(string id, bool isObjectId = true, string[] field = null)
    {
      try
      {
            var client = _database.GetCollection&lt;T&gt;(_collName);
            FilterDefinition&lt;T&gt; filter;
            if (isObjectId)
            {
                filter = Builders&lt;T&gt;.Filter.Eq("_id", new ObjectId(id));
            }
            else
            {
                filter = Builders&lt;T&gt;.Filter.Eq("_id", id);
            }

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

            //制定查询字段
            var fieldList = new List&lt;ProjectionDefinition&lt;T&gt;&gt;();
            for (int i = 0; i &lt; field.Length; i++)
            {
                fieldList.Add(Builders&lt;T&gt;.Projection.Include(field.ToString()));
            }
            var projection = Builders&lt;T&gt;.Projection.Combine(fieldList);
            fieldList?.Clear();
            return await client.Find(filter).Project&lt;T&gt;(projection).FirstOrDefaultAsync();
      }
      catch (Exception ex)
      {
            throw ex;
      }
    }
    #endregion

    #region FindList 查询集合
    /// &lt;summary&gt;
    /// 查询集合
    /// &lt;/summary&gt;
    /// &lt;param name="filter"&gt;查询条件&lt;/param&gt;
    /// &lt;param name="field"&gt;要查询的字段,不写时查询全部&lt;/param&gt;
    /// &lt;param name="sort"&gt;要排序的字段&lt;/param&gt;
    /// &lt;returns&gt;&lt;/returns&gt;
    public List&lt;T&gt; FindList(FilterDefinition&lt;T&gt; filter, string[] field = null, SortDefinition&lt;T&gt; sort = null)
    {
      try
      {
            var client = _database.GetCollection&lt;T&gt;(_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&lt;ProjectionDefinition&lt;T&gt;&gt;();
            for (int i = 0; i &lt; field.Length; i++)
            {
                fieldList.Add(Builders&lt;T&gt;.Projection.Include(field.ToString()));
            }
            var projection = Builders&lt;T&gt;.Projection.Combine(fieldList);
            fieldList?.Clear();
            if (sort == null) return client.Find(filter).Project&lt;T&gt;(projection).ToList();
            //排序查询
            return client.Find(filter).Sort(sort).Project&lt;T&gt;(projection).ToList();
      }
      catch (Exception ex)
      {
            throw ex;
      }
    }
    #endregion

    #region FindListAsync 异步查询集合
    /// &lt;summary&gt;
    /// 异步查询集合
    /// &lt;/summary&gt;
    /// &lt;param name="filter"&gt;查询条件&lt;/param&gt;
    /// &lt;param name="field"&gt;要查询的字段,不写时查询全部&lt;/param&gt;
    /// &lt;param name="sort"&gt;要排序的字段&lt;/param&gt;
    /// &lt;returns&gt;&lt;/returns&gt;
    public async Task&lt;List&lt;T&gt;&gt; FindListAsync(FilterDefinition&lt;T&gt; filter, string[] field = null, SortDefinition&lt;T&gt; sort = null)
    {
      try
      {
            var client = _database.GetCollection&lt;T&gt;(_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&lt;ProjectionDefinition&lt;T&gt;&gt;();
            for (int i = 0; i &lt; field.Length; i++)
            {
                fieldList.Add(Builders&lt;T&gt;.Projection.Include(field.ToString()));
            }
            var projection = Builders&lt;T&gt;.Projection.Combine(fieldList);
            fieldList?.Clear();
            if (sort == null) return await client.Find(filter).Project&lt;T&gt;(projection).ToListAsync();
            //排序查询
            return await client.Find(filter).Sort(sort).Project&lt;T&gt;(projection).ToListAsync();
      }
      catch (Exception ex)
      {
            throw ex;
      }
    }
    #endregion

    #region FindListByPage 分页查询集合
    /// &lt;summary&gt;
    /// 分页查询集合
    /// &lt;/summary&gt;
    /// &lt;param name="filter"&gt;查询条件&lt;/param&gt;
    /// &lt;param name="pageIndex"&gt;当前页&lt;/param&gt;
    /// &lt;param name="pageSize"&gt;页容量&lt;/param&gt;
    /// &lt;param name="count"&gt;总条数&lt;/param&gt;
    /// &lt;param name="field"&gt;要查询的字段,不写时查询全部&lt;/param&gt;
    /// &lt;param name="sort"&gt;要排序的字段&lt;/param&gt;
    /// &lt;returns&gt;&lt;/returns&gt;
    public List&lt;T&gt; FindListByPage(FilterDefinition&lt;T&gt; filter, int pageIndex, int pageSize, out long count, string[] field = null, SortDefinition&lt;T&gt; sort = null)
    {
      try
      {
            var client = _database.GetCollection&lt;T&gt;(_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&lt;ProjectionDefinition&lt;T&gt;&gt;();
            for (int i = 0; i &lt; field.Length; i++)
            {
                fieldList.Add(Builders&lt;T&gt;.Projection.Include(field.ToString()));
            }
            var projection = Builders&lt;T&gt;.Projection.Combine(fieldList);
            fieldList?.Clear();

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

            //排序查询
            return client.Find(filter).Sort(sort).Project&lt;T&gt;(projection).Skip((pageIndex - 1) * pageSize).Limit(pageSize).ToList();

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

    #region FindListByPageAsync 异步分页查询集合
    /// &lt;summary&gt;
    /// 异步分页查询集合
    /// &lt;/summary&gt;
    /// &lt;param name="filter"&gt;查询条件&lt;/param&gt;
    /// &lt;param name="pageIndex"&gt;当前页&lt;/param&gt;
    /// &lt;param name="pageSize"&gt;页容量&lt;/param&gt;
    /// &lt;param name="field"&gt;要查询的字段,不写时查询全部&lt;/param&gt;
    /// &lt;param name="sort"&gt;要排序的字段&lt;/param&gt;
    /// &lt;returns&gt;&lt;/returns&gt;
    public async Task&lt;List&lt;T&gt;&gt; FindListByPageAsync(FilterDefinition&lt;T&gt; filter, int pageIndex, int pageSize, string[] field = null, SortDefinition&lt;T&gt; sort = null)
    {
      try
      {
            var client = _database.GetCollection&lt;T&gt;(_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&lt;ProjectionDefinition&lt;T&gt;&gt;();
            for (int i = 0; i &lt; field.Length; i++)
            {
                fieldList.Add(Builders&lt;T&gt;.Projection.Include(field.ToString()));
            }
            var projection = Builders&lt;T&gt;.Projection.Combine(fieldList);
            fieldList?.Clear();

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

            //排序查询
            return await client.Find(filter).Sort(sort).Project&lt;T&gt;(projection).Skip((pageIndex - 1) * pageSize).Limit(pageSize).ToListAsync();

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


    #region Count 根据条件获取总数
    /// &lt;summary&gt;
    /// 根据条件获取总数
    /// &lt;/summary&gt;
    /// &lt;param name="filter"&gt;条件&lt;/param&gt;
    /// &lt;returns&gt;&lt;/returns&gt;
    public long Count(FilterDefinition&lt;T&gt; filter)
    {
      try
      {
            var client = _database.GetCollection&lt;T&gt;(_collName);
            return client.CountDocuments(filter);
      }
      catch (Exception ex)
      {
            throw ex;
      }
    }
    #endregion

    #region CountAsync 异步根据条件获取总数
    /// &lt;summary&gt;
    /// 异步根据条件获取总数
    /// &lt;/summary&gt;
    /// &lt;param name="filter"&gt;条件&lt;/param&gt;
    /// &lt;returns&gt;&lt;/returns&gt;
    public async Task&lt;long&gt; CountAsync(FilterDefinition&lt;T&gt; filter)
    {
      try
      {
            var client = _database.GetCollection&lt;T&gt;(_collName);
            return await client.CountDocumentsAsync(filter);
      }
      catch (Exception ex)
      {
            throw ex;
      }
    }
    #endregion
}
</code></pre>
<blockquote>
<p>6.创建 UserInfoService 类</p>
</blockquote>
<pre><code>public class UserInfoService
{
    private readonly UserInfoRepertoty _userInfoRepertoty;

    private readonly FilterDefinitionBuilder&lt;UserInfo&gt; _buildFilter;
    public UserInfoService(UserInfoRepertoty userInfoRepertoty)
    {
      _userInfoRepertoty = userInfoRepertoty;
      _buildFilter = Builders&lt;UserInfo&gt;.Filter;
    }
}
</code></pre>
<p>体验mongodb独特的使用方式,这里挑出两个具有代表性的操作进行讲解,测试数据<br>
<img src="https://img2023.cnblogs.com/blog/772322/202301/772322-20230107164902002-418256653.png" alt="image" loading="lazy"></p>
<p><strong>分页查询集合(表)</strong></p>
<ul>
<li>1.动态条件查询</li>
<li>2.查询文档指定字段</li>
<li>3.排序</li>
<li>4.分页</li>
</ul>
<p>定义查询操作</p>
<pre><code>FilterDefinition&lt;UserInfo&gt; filter = _buildFilter.Empty;
</code></pre>
<p>查询条件由查询条件构造器构建,这个地方网上很多示例写的有bug,当查询所有集合(表)数据的时候,<strong><font color="red" size="3">filter = null</font></strong> 在转换的时候会抛出异常</p>
<pre><code>//创建查询条件构造器
FilterDefinitionBuilder&lt;UserInfo&gt; _buildFilter = Builders&lt;UserInfo&gt;.Filter;
//定义查询条件
FilterDefinition&lt;UserInfo&gt; filter = null;
if(!string.IsNullOrEmpty(request.Name)) filter = _buildFilter.Eq(m =&gt; m.Name, request.Name);
</code></pre>
<p>这里有很多种类型的构造器,对应不同的操作</p>
<pre><code>//排序操作
SortDefinition&lt;UserInfo&gt; sort
//排序构造器
Builders&lt;UserInfo&gt;.Sort

修改操作
UpdateDefinition&lt;UserInfo&gt; update
//修改构造器
Builders&lt;UserInfo&gt;.Update

</code></pre>
<p>完整的查询示例,比较麻烦的地方,是针对数组的条件查询,如果嵌套的层数比较多,查询也是同理的套娃查询</p>
<pre><code>public class GetUserListRequest
{
    /// &lt;summary&gt;
    /// 名称
    /// &lt;/summary&gt;
    public string Name { get; set; }

    /// &lt;summary&gt;
    /// 年龄
    /// &lt;/summary&gt;
    public int? Age { get; set; }


    /// &lt;summary&gt;
    /// 创建时间
    /// &lt;/summary&gt;
    public DateTime CreateTime { get; set; }

    /// &lt;summary&gt;
    /// 合作伙伴
    /// &lt;/summary&gt;
    public Partner PartnerList { get; set; }

    /// &lt;summary&gt;
    /// 信息
    /// &lt;/summary&gt;
    public Info Info { get; set; }
}

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

    SortDefinition&lt;UserInfo&gt; sort = Builders&lt;UserInfo&gt;.Sort.Ascending(m =&gt; m.Age);

    if (!string.IsNullOrEmpty(request.Name))
    {
      filter = _buildFilter.Eq(m =&gt; m.Name, request.Name);
    }
    if (request.Age.HasValue)
    {
      filter = _buildFilter.Eq(m =&gt; m.Age, request.Age);
    }
    if (request.PartnerList != null)
    {
      if (request.PartnerList.Status.HasValue)
      {
            filter = _buildFilter.ElemMatch("PartnerList", Builders&lt;Partner&gt;.Filter.Eq(m =&gt; m.Status, request.PartnerList.Status));
      }
    }
    if (request.Info != null)
    {
      if (!string.IsNullOrEmpty(request.Info.Code))
      {
            filter = _buildFilter.Eq(m =&gt; m.Info.Code, request.Info.Code);
      }
    }
    var list = await _userInfoRepertoty.FindListByPageAsync(filter,1,3, new string[] { "Name","Age", "CreateTime" }, sort);
    return list;
}
</code></pre>
<blockquote>
<p>动态条件查询(查询全部)</p>
</blockquote>
<pre><code>var list = await _userInfoRepertoty.FindListByPageAsync(filter, 1, 30);
</code></pre>
<p><img src="https://img2023.cnblogs.com/blog/772322/202301/772322-20230107165330867-1282156814.png" alt="image" loading="lazy"></p>
<blockquote>
<p>条件查询,排序,分页,查询指定字段</p>
</blockquote>
<pre><code>var list = await _userInfoRepertoty.FindListByPageAsync(filter,1,3, new string[] { "Name","Age", "CreateTime" }, sort);
</code></pre>
<p><img src="https://img2023.cnblogs.com/blog/772322/202301/772322-20230107170055863-885107849.png" alt="image" loading="lazy"><br>
除了使用对象模型进行操作,也可以直接使用mongodb原生的BsonDocument进行操作</p>
<pre><code>var buildFilter = Builders&lt;BsonDocument&gt;.Filter;
FilterDefinition&lt;BsonDocument&gt; 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&lt;BsonDocument&gt;.Sort;
var list = await collection.Find(filter).Sort(sort.Descending("age")).ToListAsync();
</code></pre>
<p><strong>修改集合(表)的数据</strong></p>
<ul>
<li>1.修改满足条件的文档</li>
<li>2.修改文档的部分字段</li>
</ul>
<pre><code>public async Task UpdateUserInfo()
{
    //修改条件
    FilterDefinition&lt;UserInfo&gt; filter = _buildFilter.Empty;
    filter = _buildFilter.Eq(m =&gt; m.Name, "tibos");
    filter = _buildFilter.ElemMatch(list =&gt; list.PartnerList, child =&gt; child.Status == 1);


    //修改字段
    var update = Builders&lt;UserInfo&gt;.Update.Set("Age",100).Set("PartnerList.$.Name", "ppp").Set("PartnerList.$.Status", "");
    await _userInfoRepertoty.UpdateManayAsync(update, filter);
}
</code></pre><br><br>
来源:https://www.cnblogs.com/tibos/p/17033046.html
頁: [1]
查看完整版本: .net core操作MongoDB