1

Say if I have a result like this:

    {
        "_id" : ObjectId("5b722d06c23b5f2bd0329a41"),
        "name" : "test",
        "item" : {
            "_id" : ObjectId("5b722d07c23b5f2bd0329a53"),
            "display_name" : "",
            "image" : "http://via.placeholder.com/700x500/ffffff/000000/?text=No%20Image&",
            "is_private" : true,
            "details" : [
                {
                    "is_private" : false,
                    "type" : "text",
                    "_id" : ObjectId("5b722d06c23b5f2bd0329a44"),
                    "title" : "Name",
                    "content" : "",
                    "order" : 0
                },
                {
                    "is_private" : false,
                    "type" : "text",
                    "_id" : ObjectId("5b722d06c23b5f2bd0329a43"),
                    "title" : "Price",
                    "content" : "",
                    "order" : 1
                },
                {
                    "is_private" : false,
                    "type" : "text",
                    "_id" : ObjectId("5b722d06c23b5f2bd0329a42"),
                    "title" : "Company",
                    "content" : "",
                    "order" : 2
                }
            ],
            "tags" : [ ],
            "__v" : 0
        }
    }

and I want to filter by item.details.is_private, how should I do this? I want to return all properties of item but filter out any item.details.is_private if it is true

I am currently projecting it as:

{
    "$project": {
        name: 1,
        item: 1
    }
}

but am not sure how to implement $filter in this setting

A. L
  • 11,695
  • 23
  • 85
  • 163
  • 1
    Try `{ "$addFields": { "item.details": { "$filter": { "input": "$item.details", "cond": { "$eq": [ "$$this.is_private", true ] } } } } }` – s7vr Aug 14 '18 at 03:38
  • Possible dupe of https://stackoverflow.com/q/3985214/2683814 – s7vr Aug 14 '18 at 03:39
  • @Veeram don't think it's a duplicate because mine is 1 level down, so I can't just use a straight up `$filter` like Anthony did. I might need to do some kind of `$unwind` into a `$redact` back into a `$concatArray` but I'm not sure if that's the right path. – A. L Aug 14 '18 at 03:43

1 Answers1

1

You can try using $addsFields with $filter aggregation

db.collection.aggregate([
  { "$addFields": {
    "item.details": {
      "$filter": {
        "input": "$item.details",
        "as": "detail",
        "cond": {
          "$eq": [ "$$detail.is_private", true ]
        }
      }
    }
  }}
])
Ashh
  • 44,693
  • 14
  • 105
  • 132
  • this only returns `item.details` though, I also need the rest of the `item` stuff – A. L Aug 14 '18 at 03:41
  • isn't there a better way to do this? Since, if the document updates with additional fields in the future, then I'll have to account for every single unique field – A. L Aug 14 '18 at 03:44
  • Don't ever take nested documents in your model to keep better performance and it's the best way to do work with mongodb... – Ashh Aug 14 '18 at 03:47
  • cool, seems to work. I'm guessing that `$addFields` is just overiding the original `details` then – A. L Aug 14 '18 at 03:58
  • @A.Lau precisly – Ashh Aug 14 '18 at 03:59