首页 > 解决方案 > 使用 C# 和 MongoDriver 从 MongoDB 中的文档数组中过滤文档

问题描述

我有一个 MongoDB(在 Cosmos DB 上运行),并试图根据列表过滤掉数组中的子文档。我在 Mongo Shell 中取得了一些成功,但我没有实现我的目标,在 C# 中使用 MongoDriver 也没有成功。

我想要做的是例如在我的数据库中给出这两个文档:

{
    "person" : "John",
    "pet" : [
        {
            "name" : "Spot",
            "type" : "Dog"
        },
        {
            "name" : "Ms. Whiskers",
            "type" : "Cat"
        },
        {
            "name" : "Jack",
            "type" : "Hamster"
        }
    ]
},
{
    "person" : "Jane",
    "pet" : [
        {
            "name" : "Max",
            "type" : "Lizard"
        }
    ]
}

我想过滤掉类型既不是狗也不是仓鼠的宠物子文档。

{
    "person" : "John",
    "pet" : [
        {
            "name" : "Ms. Whiskers",
            "type" : "Cat"
        }
    ]
},
{
    "person" : "Jane",
    "pet" : [
        {
            "name" : "Max",
            "type" : "Lizard"
        }
    ]
}

我最接近的是以下 Shell 命令作为 $nin 未知操作员错误。

db.collection.aggregate([{ 
    $project: {
        pet: {
            $filter: {
                input: "$pet", 
                as: "p",
                cond: {$ne: [ "$$p.type", "dog" ]}
            }
        }
    }
}
]).pretty()

但我不知道如何将其转换为 C# Mongo Driver 查询,有人可以帮忙吗?

Cosmos 模拟了 3.6 版本的 MongoDB,如果这对我的场景有任何影响,它的版本刚刚升级到 4.0。我正在使用 MongoDriver v2.12.2 和 .NET Core 3.1

标签: c#mongodb

解决方案


首先,您需要像这样制作pet属性IEnumerable<T>

public class item : Entity
{
    public IEnumerable<pet> pet { get; set; }
}

然后您可以使用该Queryable接口过滤掉不需要的类型,如下所示:

var result = await collection
    .AsQueryable()
    .Select(x => new item
    {
        person = x.person,
        pet = x.pet.Where(p => p.type != "Dog" && p.type != "Hamster")
    })
    .ToListAsync();

或者您可以将排除项设置为字符串数组并更改 where 子句,如下所示:


var excludes = new[] { "Dog", "Hamster" };

var result = await collection
    .AsQueryable()
    .Select(x => new item
    {
        person = x.person,
        pet = x.pet.Where(p => !excludes.Contains(p.type))
    })
    .ToListAsync();

推荐阅读