简体   繁体   中英

Filtering documents from document array in MongoDB with C# and MongoDriver

I have a MongoDB (running on Cosmos DB), and am trying to filter out sub-documents in an array, based on a list. I have had some success in the Mongo Shell but I did not achieve my goal, and no success in C# with the MongoDriver.

What I want to do is eg given these two documents in my database:

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

I want to filter out the pet sub-documents where the type is neither a dog or a hamster.

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

The closest I've been was the following Shell command as $nin unknown operator error.

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

But I cannot figure out how to translate this to a C# Mongo Driver query, can anyone help?

The Cosmos emulates a version 3.6 MongoDB, which have just got a version bump to 4.0 if that does any difference for my scenario. I am using MongoDriver v2.12.2, and .NET Core 3.1

first of all, you need to make the pet property IEnumerable<T> like so:

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

then you can use the Queryable interface to filter out the unneeded types like so:

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

or you can make the exclusions an array of strings and change the where clause like so:


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();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM