1

Let's assuming 2 objects:

class A
{
    string id;
    List<B> items;
}

class B
{
    string color;
    string name;
}

I would like to do a query where:

_ => _.id == myqueryid && _.items.any(t => t.color == "yellow)

so far.. so good

now, I would like to recover only the B type object that was matched, not the whole object; how can I do that?

bonus question: is there a way to recover a single field from the B type object?


here's the code right now

var K = Driver.Find(_ => _.Id == Id && _.Items.Any(__ => __.Color == "Yellow"));

that part works. it recovers the right objects

var K = Driver.Find(_ => _.Id == Id && _.Items.Any(__ => __.Color == "Yellow").Project(P);

and my projection is:

Expression(_ => _.Ledger[-1])

but somehow I don't get the data I need. If I project to a dynamic and use Include, I get it (along with _id), but it's not ideal.


after more testing:

.Include(_ => _.items[-1].color).Exclude(_ => _._id));

I would expect this to return color, but it returns the matching B object...

Thomas
  • 10,933
  • 14
  • 65
  • 136
  • I read that one, but it doesn't help with with the C# syntax – Thomas Nov 04 '17 at 20:02
  • I added the code (not literal copy / paste since I'm not at the same computer, but the gist of it is there) – Thomas Nov 04 '17 at 20:32
  • Nonetheless this is a [duplicate question](https://stackoverflow.com/questions/3985214/retrieve-only-the-queried-element-in-an-object-array-in-mongodb-collection), at least in terms of implementing the result. It is not possible to project array members like this with standard projection. That means you need an aggregate `$project` in order to alter the array structure returned, and that means you `$filter` the array elements in order to just get the matched ones. It is the only way to really do it. – Neil Lunn Nov 04 '17 at 21:19

1 Answers1

2

You can try Aggregate like this.

var result = collection.Aggregate()
                .Match(_ => _.id == Id && _.items.Any(t => t.color == "yellow"))
                .Unwind<A>(new StringFieldDefinition<A>("items"))
                .ReplaceRoot<B>(new BsonValueAggregateExpressionDefinition<A, B>(@"$items"))
                .First();
Serkan Arslan
  • 13,158
  • 4
  • 29
  • 44