Access filtering in tree structure

Thanks for the clarification... I think I finally understand what you're looking for, sorry it took so long :slight_smile:

I believe this should be possible. Here's a reproduction to test it out, see if this works for your needs (i tried a few combinations and it seemed to work based on what you said. First, the mapping and a document:

PUT /test/
{
  "mappings": {
    "_doc": {
      "properties": {
        "Id": {
          "type": "keyword"
        },
        "AncestorIdPath": {
          "type": "keyword"
        },
        "AccessModels": {
          "type": "nested",
          "properties": {
            "Groups": {
              "type": "keyword"
            },
            "Users": {
              "type": "keyword"
            }
          }
        }
      }
    }
  }
}

POST /test/_doc/
{
    "Id": 3,
    "AncestorIdPath": [1, 2],
    "AccessModels": [
    	{
    		"Groups": [1],
    		"Users": [1, 2]
    	},
    	{
    		"Groups": [3],
    		"Users": []
    	},
    	{
    		"Groups": [2],
    		"Users": [2, 3]
    	}
    ]
}

And now the first query you specified (ID==3, groupIds==1,3):

POST /test/_search
{
  "query": {
    "bool": {
      "must_not": [
        {
          "nested": {
          "path": "AccessModels",
          "query": {
            "bool": {
              "must_not": [
                {
                  "term": {
                    "AccessModels.Users": {
                      "value": 3
                    }
                  }
                },
                {
                  "terms": {
                    "AccessModels.Groups": [1, 3]
                  }
                }
              ]
            }
          }
        }
        }
      ]
    }
  }
} 

The arrangement is a little funky. The inner-most boolean must_not finds all nested documents that do not match the ID/Group criteria. The middle nested query will then match all root documents where at least one of it's children do not match the criteria. Finally, the outer-most boolean must_not will negate the set of documents where one child is missing the criteria, essentially finding the set of docs that do have all the criteria.

Here's the second query (ID=4, Groups=1,2) which doesn't match the document:

POST /test/_search
{
  "query": {
    "bool": {
      "must_not": [
        {
          "nested": {
          "path": "AccessModels",
          "query": {
            "bool": {
              "must_not": [
                {
                  "term": {
                    "AccessModels.Users": {
                      "value": 4
                    }
                  }
                },
                {
                  "terms": {
                    "AccessModels.Groups": [1, 2]
                  }
                }
              ]
            }
          }
        }
        }
      ]
    }
  }
} 

Lemme know if that works for you, and thanks again for your patience and extra clarification :slight_smile:

1 Like