0

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.

1 Answer 1

2

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!

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks. First query is what I need. But it returns all the arr children objects in result instead of the criteria I applied.
No problem =). This is just a filter, can you share full code you use to retrieve data?
This is the code. Included your first snippet. Just class names are different.
Is thr a way to make is generic using T

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.