Excluding from a Predicate Object in a Query

I have an object that contains multiple objects, this is a simplification of the project I am try to address. The parent object has a predicate of objects stored within it. I need a list of the parent objects which either only contains objects with the desired attribute values or does not contain objects with the undesired values.

In the below example I am looking for the boxes which do not have any red devices, or the boxes which only have green devices.

The schema is

color: string .
devices: [uid] .
in_box: uid .

type device {
    color
    in_box
}
type box {
    devices

Sample Query:

{
      query(func: Type(box) {
         uid
        device {
             uid
             color 
        }
    }
}

Returns:

{'query': [{'uid' : '0x1', 'devices': [{'uid': '0x2', 'color': 'green'}, {'uid': '0x3', 'color': 'green'}],
[{'uid' : '0x4', 'devices': [{'uid': '0x5', 'color': 'green'}, {'uid': '0x6', 'color': 'red'}],
[{'uid' : '0x7', 'devices': [{'uid': '0x8', 'color': 'red'}, {'uid': '0x9', 'color': 'green'}]]}

I would like a query that would only return the box without any ‘red’ devices, in this example, '0x1.

Try

{
      query(func: Type(box))  @cascade {
         uid
        device @filter(NOT eq(color, "red")) {
             uid
             color 
        }
    }
}

Thank you for taking the time to response.

This still resulted in boxes with “red” devices showing up, but only listing the “green” devices.

{'query': [{'uid' : '0x1', 'devices': [{'uid': '0x2', 'color': 'green'}, {'uid': '0x3', 'color': 'green'}],
[{'uid' : '0x4', 'devices': [{'uid': '0x5', 'color': 'green'}],
[{'uid' : '0x7', 'devices': [{'uid': '0x9', 'color': 'green'}]]}

hum, so maybe something like this

{
      q as var(func: has(devices)) {
         uid
          rm as devices @filter(eq(color, "red") ) 
    }
    query(func: uid(q)) @filter(not uid_in(devices, uid(rm))) @cascade {
       uid
       devices {
             uid
             color 
        }
    }

}

Question: If q is the set of boxes which has ‘red’ devices. and the query is against q with a filter of objects that are not in q, shouldn’t this result in a null set?

I could not understand your question.

The logic of this whole query is:

“Only return devices that don’t contain the UIDs found in the q variable” And cascade does the rest.

The solution that worked in my sandbox was:

{
    var(func: Type(box)) @cascade(devices) @normalize {
        dev AS devices @filter(eq(color, "red"))
    }
    query(func: Type(box)) @filter(uid_in(devices, uid(dev))) {
        uid
        devices {
            uid
            color
        }
    }
}

This provided expected results.

It however doesn’t scale when tested in the development environment. which only has ~150k objects.
image