benjamin54
benjamin54

Reputation: 1300

Filter data from MongoDB with .NET driver

I need to create a filter for my mongo collection filter. I'm using Mongo driver 2 for .NET.

Here is my JSON.

[
    {
        "a": "val_a0",
        "b": "val_b0",
        "arr":[
            {
                "c": "val_c0",
                "d": "val_d0"
            },
            {
                "c": "val_c1",
                "d": "val_d1"
            },
            {
                "c": "val_c2",
                "d": "val_d2"
            }
        ]
    },
    {
        "a": "val_a1",
        "b": "val_b1",
        "arr":[
            {
                "c": "val_c3",
                "d": "val_d3"
            },
            {
                "c": "val_c4",
                "d": "val_d4"
            },
            {
                "c": "val_c5",
                "d": "val_d5"
            }
        ]
    },
...
]

I need to apply filter on root level property a and nested property c. My filter code is:-

public class MyFilterClass
{
    public string a { get; set; }

    public MyFilterNestedClass nested { get; set; }
}

public class MyFilterNestedClass
{
    public string c { get; set; }
}

And filter code:-

public FilterDefinition<MyClass> Build(MyFilterClass filter)
{
    var _filterDef = Builders<MyClass>.Filter.Empty;

    _filterDef &= Builders<MyClass>.Filter.Eq(t => t.a, filter.a); // Filter by root level property [a]

    // Filter by nested level property [c]
    // First way
    _filterDef &= Builders<MyClass>.Filter.Eq(t => t.arr.First(w => w.c == filter.MyFilterNestedClass.c).c, filter.arr.c);

    // Second way
    _filterDef &= builders<MyClass>.filter.where(t => t.a == filter.a &&
                                                    t.arr.first(w => w.c == filter.MyFilterNestedClass.c) != null);

    return _filterDef;
}

I tried using both the ways to apply nested property criteria. But it never returns any documents from database.

Upvotes: 0

Views: 1237

Answers (1)

BOR4
BOR4

Reputation: 630

Maybe something like this?

var filter = Builders<MyClass>.Filter.And(
            Builders<MyClass>.Filter.Eq(t => t.a, filter.a),
            Builders<MyClass>.Filter.ElemMatch(t => t.arr, i => i.c == filter.nested.c));
return filter;

I tested it on similar example I had and It worked so I hope it will work for you as well.

EDIT: seems you need first element explicitly. Sorry I didn't read question with complete understanding. If you want result only if first element matches try this:

var filter = Builders<MyClass>.Filter.And(
            Builders<MyClass>.Filter.Eq(t => t.a, filter.a),
            Builders<MyClass>.Filter.Eq(t => t.arr.ElementAt(0).c, filter.nested.c));
return filter;

cheers!

Upvotes: 2

Related Questions