在使用C#的MongoDB集合中的嵌入文档的Where子句查询中的投影

时间:2016-06-14 00:43:54

标签: c# mongodb mongodb-query mongodb-.net-driver

  

在DB中过滤集合而不是内存

我有一个模型类,将它保存在MongoDB集合中,然后按照我下面提到的期望进行查询。

我的模特课程:

public Class Employee
{
    public ObjectId Id { get; set; }
    public string EmpID { get; set; }
    public string EmpName { get; set; }
    public List<Mobile> EmpMobile { get; set; }
    public bool IsLive { get; set; }
}

public Class Mobile
{
    public string MobID { get; set; }
    public string MobNumber { get; set; }
    public bool IsPreferred { get; set; }
    public bool IsLive { get; set; }
}

值是

List<Employee> EmpInfo = new List<Employee>() {
new Employee()
{
    EmpID = "100",
    EmpName = "John",
    EmpMobile = new List<Mobile>()
    {
        new Mobile() { MobNumber = "55566610", IsPreferred = true, IsLive = false },
        new Mobile() { MobNumber = "55566611", IsPreferred = false, IsLive = true },
    },
    IsLive = true
},

new Employee()
{
    EmpID = "101",
    EmpName = "Peter",
    EmpMobile = new List<Mobile>()
    {
        new Mobile() { MobNumber = "55566610", IsPreferred = true, IsLive = false },
        new Mobile() { MobNumber = "55566611", IsPreferred = false, IsLive = false },
    },
    IsLive = true
},

new Employee()
{
    EmpID = "102",
    EmpName = "Jack",
    EmpMobile = new List<Mobile>()
    {
        new Mobile() { MobNumber = "55566610", IsPreferred = true, IsLive = true },
        new Mobile() { MobNumber = "55566611", IsPreferred = false, IsLive = true },
    },
    IsLive = false
}

}

collectionEmpInfo.InsertMany(EmpInfo);
var empList = collectionEmpInfo.Find(new BsonDocument()).ToList();

现在我希望在嵌入式文档中仅选择 EmpInfo.IsLive == true ,我只需要 EmpInfo.EmpMobile.IsLive == true 满意的移动文档

我的预期输出:

List<Employee> EmpInfo = new List<Employee>() {
new Employee()
{
    EmpID = "100",
    EmpName = "John",
    EmpMobile = new List<Mobile>()
    {
        new Mobile() { MobNumber = "55566611", IsPreferred = false, IsLive = true }
    },
    IsLive = true
},

new Employee()
{
    EmpID = "101",
    EmpName = "Peter",
    EmpMobile = new List<Mobile>()
    {

    },
    IsLive = true
}

}

请帮助我使用 c#MongoDB 为我的预期输出编写 Where子句查询

  

注意:在DB中过滤集合而不是内存

我的MongoDB库和连接

IMongoClient _client = new MongoClient();
IMongoDatabase _database = _client.GetDatabase("Test");

3 个答案:

答案 0 :(得分:0)

我认为这可以解决您遇到的问题:

var collection = _database.GetCollection<Employee>("employee"); // (1)

var filterBuilder = Builders<BsonDocument>.Filter;
var filter = filterBuilder.Eq("IsLive", true) & filterBuilder.Eq("EmpMobile.IsLive", true); // (2)

var results = await collection.FindAsync(filter).ToListAsync(); // (3)

(1):您需要使用包含要查询的数据的集合名称更改集合名称。另请注意,它请求TDocument作为通用参数。似乎Employee不会继承TDocument,但您可以这样做,或者您可以为此目的创建另一个DTO类。

(2):您可以使用位AND运算符(&)组合条件。

此外,您可以直接查询数组的内部值(您在类中将其作为列表)。事实证明,如果任何数组值满足条件,它将返回文档。在您的示例中,这应返回EmpID 100的文档,但它将包含MobileNumber中的两个{}。您检索了满足条件的文档,但您完整地检索了文档。

(3)最后,将结果呈现为一个列表,以便将它们存储在内存中。或者,您可以使用cursor.MoveNextAsync()来查看结果,但这样可以延长与MongoDB的连接时间。

您可以使用MongoDB文档的Find or Query Data with C# Driver中的示例找到大部分信息。

答案 1 :(得分:0)

你的方法有几个int。

首先您使用collectionEmpInfo.InsertOne(EmpInfo);我假设您要使用InsertMany

对于对集合进行过滤,您必须知道过滤器将影响整个对象是否被检索,因此在实体内的嵌入式数组上添加过滤器不会过滤数组,而是确定是否检索整个对象或不是基于它是否与嵌入式阵列上的查询条件匹配。我的建议是仅对查询中的员工应用过滤器,并在内存中过滤结果集。

var filter = filterBuilder.Eq("IsLive", true);

var results = await collection.FindAsync(filter).ToListAsync();

现在按照

过滤内存中的结果集合
var filteredResults = results.ForEach(employee => employee.EmpMobile = employee.EmpMobile.Where(mob => mob.isLive).ToList());

答案 2 :(得分:0)

<强> 修改

添加了projection - 所以选定的数组只包含IsLive==true

的文档

我认为使用类型化查询更容易,因为c#是强类型语言。 我使用ElemMatch,因为它用于扫描数组并查找匹配元素。

var filterDef = new FilterDefinitionBuilder<Employee>();
var filter = filterDef.Eq(x => x.IsLive, true);

var projectDef = new ProjectionDefinitionBuilder<Employee>();
var projection = projectDef.ElemMatch<Mobile>("EmpMobile", "{IsLive:true}");            

var empList = collectionEmpInfo.Find(filter).Project<Employee>(projection).ToList();