C# MongoDB多条件查询,多集合查询示例。动态过滤方法使用。BsonDocument转成普通的实体对象

  • Post author:
  • Post category:其他


直接上代码

MongoDB.Driver包提供的LINQ查询语法。以下是一个使用C#和MongoDB进行多条件查询、多表联查的示例代码:



多条件查询,多表关联

using MongoDB.Driver;
using MongoDB.Bson;
using System.Linq;

namespace MyMongoDBDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            string connectionString = "mongodb://localhost:27017";
            MongoClient mongoClient = new MongoClient(connectionString);
            var database = mongoClient.GetDatabase("mydatabase");

            // 获取集合
            var ordersCollection = database.GetCollection<BsonDocument>("orders");
            var customersCollection = database.GetCollection<BsonDocument>("customers");

            // 多条件查询 orders 集合
            var filter = Builders<BsonDocument>.Filter.And(
                Builders<BsonDocument>.Filter.Eq("status", "active"),
                Builders<BsonDocument>.Filter.Gte("totalAmount", 100));

            var orders = ordersCollection.Find(filter).ToList();
            foreach (var order in orders)
            {
                // 获取关联的 customer 记录
                var customerId = order.GetValue("customerId").ToString();
                var customerFilter = Builders<BsonDocument>.Filter.Eq("_id", ObjectId.Parse(customerId));
                var customer = customersCollection.Find(customerFilter).FirstOrDefault();

                // 处理数据
                // ...
            }

            // 多表联查
            var results = from order in ordersCollection.AsQueryable()
                          join customer in customersCollection.AsQueryable() on order.GetValue("customerId").ToString() equals customer.GetValue("_id").ToString()
                          select new
                          {
                              OrderId = order.GetValue("_id").ToString(),
                              CustomerName = customer.GetValue("name").ToString()
                          };

            foreach (var result in results)
            {
                // 处理数据
                // ...
            }
        }
    }
}



多表关联并且多条件查询

可以使用 MongoDB 的聚合管道(Aggregation Pipeline)来实现多表关联并且多条件查询的操作。以下是一个示例代码,假设有两个集合分别是“orders”和“customers”,它们的文档结构如下:

orders 集合:

{
    "_id": ObjectId("609f99c81de502c6a4f5299b"),
    "order_id": 10001,
    "customer_id": 20001,
    "order_date": "2022-05-01",
    "total_amount": 100.0
}
customers 集合:

{
    "_id": ObjectId("609f99c81de502c6a4f5299c"),
    "customer_id": 20001,
    "customer_name": "张三",
    "customer_email": "zhangsan@example.com"
}

从上述数据结构可知,orders 集合中的 customer_id 字段与 customers 集合中的 customer_id 字段关联。

查询需求:查找 2022 年 5 月 1 日以后下单金额大于等于 50 元的订单信息,并返回订单所属客户的姓名和邮箱。

代码实现如下:

csharp

using MongoDB.Driver;
using MongoDB.Bson;

var client = new MongoClient("mongodb://localhost:27017");
var database = client.GetDatabase("mydb");

var ordersCollection = database.GetCollection<BsonDocument>("orders");
var customersCollection = database.GetCollection<BsonDocument>("customers");

var pipeline = new BsonDocument[]
{
    // 过滤条件:订单日期在 2022 年 5 月 1 日以后,订单金额大于等于 50 元
    new BsonDocument("$match", new BsonDocument
    {
        { "order_date", new BsonDocument("$gte", new BsonDateTime(new DateTime(2022, 5, 1))) },
        { "total_amount", new BsonDocument("$gte", 50.0) }
    }),
    // 关联 customers 集合,并按 customer_id 分组
    new BsonDocument("$lookup", new BsonDocument
    {
       
  		{ "from", "customers" }, // 连接的集合名称
        { "localField", "customer_id" }, // 当前集合的关联字段
        { "foreignField", "customer_id" }, // 目标集合的关联字段
        { "as", "customer_info" } // 输出结果中的新字段名
    }),
    // 过滤条件:存在客户信息(即 customers 集合中存在对应的文档)
    new BsonDocument("$match", new BsonDocument
    {
        { "customer_info", new BsonDocument("$ne", new BsonArray()) }
    }),
    // 投影出返回结果需要的字段
    new BsonDocument("$project", new BsonDocument
    {
        { "_id", 0 },
        { "customer_name", "$customer_info.customer_name" },
        { "customer_email", "$customer_info.customer_email" },
        { "order_id", 1 },
        { "total_amount", 1 }
    })
};

var result = ordersCollection.Aggregate<BsonDocument>(pipeline).ToList();

在上面的代码中,我们首先从 MongoDB 客户端获取了 orders 和 customers 两个集合的引用,然后使用聚合管道进行多表关联查询。具体而言,聚合管道的操作包括:

$match 操作:过滤出订单日期在 2022 年 5 月 1 日以后、订单金额大于等于 50 元的订单。

$lookup 操作:将上一步得到的订单和 customers 集合关联起来,按照 customer_id 分组。

$match 操作:过滤出存在客户信息的订单。

$project 操作:投影出需要返回的字段(即客户姓名、邮箱、订单号和总金额)。

最后,我们使用 ToList() 方法将查询结果转换成一个 List 类型的对象,并存储在变量 result 中。



多表关联并且多条件查询,使用lambda表达式

using MongoDB.Driver;
using MongoDB.Bson;

var client = new MongoClient("mongodb://localhost:27017"); // 连接 MongoDB 服务
var database = client.GetDatabase("mydb"); // 获取数据库实例

var ordersCollection = database.GetCollection<BsonDocument>("orders"); // 获取 orders 集合实例
var customersCollection = database.GetCollection<BsonDocument>("customers"); // 获取 customers 集合实例

var result = ordersCollection.Aggregate()
    .Lookup("customers", "customer_id", "customer_id", "customer_info") // $lookup 管道操作
    .Unwind("customer_info") // $unwind 管道操作
    .Match(Builders<BsonDocument>.Filter.And( // $match 管道操作,多条件查询
        Builders<BsonDocument>.Filter.Gte("order_date", new BsonDateTime(new DateTime(2023, 1, 1))), // 订单日期大于等于指定日期
        Builders<BsonDocument>.Filter.Lte("order_date", new BsonDateTime(new DateTime(2023, 2, 1))), // 订单日期小于等于指定日期
        Builders<BsonDocument>.Filter.ElemMatch<BsonValue>("items", Builders<BsonValue>.Filter.Eq("product_name", "iPhone 14")), // 订单中包含商品名称为 iPhone 14 的商品
        Builders<BsonDocument>.Filter.Eq("customer_info.customer_name", "张三") // 客户姓名为张三
    ))
    .Project<OrderCustomer>(p => new OrderCustomer // $project 管道操作
    {
        OrderId = p["order_id"].AsInt32,
        CustomerName = p["customer_info"]["customer_name"].AsString,
        CustomerEmail = p["customer_info"]["customer_email"].AsString,
        TotalAmount = p["total_amount"].AsDouble
    })
    .ToList();

public class OrderCustomer // 查询结果对象的定义
{
    public int OrderId { get; set; }
    public string CustomerName { get; set; }
    public string CustomerEmail { get; set; }
    public double TotalAmount { get; set; }
}

在上述代码中,我们使用了 MongoDB 的 Aggregate 方法和一系列 Lambda 表达式来实现多表关联并且多条件查询。具体而言,Lambda 表达式包括:

.Lookup 方法:连接 customers 集合,并将匹配的文档作为 customer_info 数组字段添加到输出文档。

.Unwind 方法:展开 customer_info 数组字段,以便进行后续的筛选操作。

.Match 方法:根据多个条件对数据进行筛选,这里使用了 And 运算符组合多个 Filters。其中:

Builders.Filter.Gte(“order_date”, new BsonDateTime(new DateTime(2023, 1, 1))):订单日期大于等于 2023 年 1 月 1 日。

Builders.Filter.Lte(“order_date”, new BsonDateTime(new DateTime(2023, 2, 1))):订单日期小于等于 2023 年 2 月 1 日。

Builders.Filter.ElemMatch(“items”, Builders.Filter.Eq(“product_name”, “iPhone 14”)):订单中包含商品名称为 iPhone 14 的商品。

Builders.Filter.Eq(“customer_info.customer_name”, “张三”):客户姓名为张三。

.Project 方法:投影输出文档的字段,创建一个自定义类型 OrderCustomer 实例,包括订单号、客户姓名、客户邮箱和总金额等字段。

最后,我们调用 ToList() 方法将查询结果转换成一个 List 类型的对象,并存储在变量 result 中。如果需要更改查询条件或者查询结果的类型,则可以修改相应的 Lambda 表达式。



动态过滤

Builders.Filter是MongoDB .NET Driver提供的用于动态创建过滤器的静态类。下面是常用的几个Filter方法及其用法:

Eq 用法:Builders.Filter.Eq(fieldName, value)

说明:生成一个用于判断某个字段等于指定值value的过滤器。

示例:Builders.Filter.Eq(“Level”, “ERROR”) 判断Level字段是否等于”ERROR”

Lt 用法:Builders.Filter.Lt(fieldName, value)

说明:生成一个用于判断某个字段小于指定值value的过滤器。

示例:Builders.Filter.Lt(“Timestamp”, DateTime.Today) 判断Timestamp字段是否小于今天

Gt 用法:Builders.Filter.Gt(fieldName, value)

说明:生成一个用于判断某个字段大于指定值value的过滤器。

示例:Builders.Filter.Gt(“Timestamp”, DateTime.Today.AddDays(-7)) 判断Timestamp字段是否大于7天前

Lte 用法:Builders.Filter.Lte(fieldName, value)

说明:生成一个用于判断某个字段小于等于指定值value的过滤器。

示例:Builders.Filter.Lte(“Timestamp”, DateTime.Today) 判断Timestamp字段是否小于等于今天

Gte 用法:Builders.Filter.Gte(fieldName, value)

说明:生成一个用于判断某个字段大于等于指定值value的过滤器。

示例:Builders.Filter.Gte(“Timestamp”, DateTime.Today.AddDays(-7)) 判断Timestamp字段是否大于等于7天前

And 用法:Builders.Filter.And(filter1, filter2, …)

说明:生成一个用于同时满足多个过滤器条件的过滤器。

示例:Builders.Filter.And( Builders.Filter.Eq(“Level”, “ERROR”), Builders.Filter.Gte(“Timestamp”, DateTime.Today) ) 判断Level字段是否等于”ERROR”且Timestamp字段大于等于今天

Or 用法:Builders.Filter.Or(filter1, filter2, …)

说明:生成一个用于满足多个过滤器条件之一的过滤器。

示例:Builders.Filter.Or( Builders.Filter.Eq(“Level”, “ERROR”), Builders.Filter.Gte(“Timestamp”, DateTime.Today) ) 判断Level字段等于”ERROR”或Timestamp字段大于等



清空集合,删除数据库

IMongoCollection<BsonDocument> collection = database.GetCollection<BsonDocument>("mycollection");
collection.DeleteMany(Builders<BsonDocument>.Filter.Empty);



标题清除数据库

string connectionString = "mongodb://localhost:27017";
MongoClient mongoClient = new MongoClient(connectionString);
mongoClient.DropDatabase("mydatabase");



BsonDocument转成普通的实体对象

using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;

public class Person
{
    [BsonId]
    public ObjectId Id { get; set; }

    [BsonElement("name")]
    public string Name { get; set; }

    [BsonElement("age")]
    public int Age { get; set; }
}
using MongoDB.Bson;
using MongoDB.Driver;
using MongoDB.Bson.Serialization;

string connectionString = "mongodb://localhost:27017";
MongoClient mongoClient = new MongoClient(connectionString);
var database = mongoClient.GetDatabase("mydatabase");
var collection = database.GetCollection<BsonDocument>("people");

BsonDocument bsonDocument = collection.Find(x => x["_id"] == new ObjectId("601f501c39e48013f038fd6a")).FirstOrDefault();
var person = BsonSerializer.Deserialize<Person>(bsonDocument);



版权声明:本文为zxb11c原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。