constraints

Constraints in Find* commands

The constraints block is used to specified search/filter criteria over the properties defined for objects (Entity, Image, Video, Connection, etc).

Supported operators for properties are:

  • “<” (less than)
  • “<=” (less or equal than)
  • “==” (equal to)
  • “!=” (different than)
  • “>” (greater than)
  • “>=” (greater or equal than)
  • “in” (is in)

Constraints for specific properties are defined as key-value pairs, where the key is the name of the property and the value is an array with operators and constraints values. Here is an example:

"constraints": {
    "property1": [ ">=", 20, "<=", 90 ],
    "property2": [ "<=", value2 ],
    "property3": [ "==", value ]
}

The “in” operator expects an array of values to check a given property’s value against to find match(es), as follows:

"constraints": {
    "property1": [ ">=", 20, "<=", 90 ],
    "property2": [ "<=", value2 ],
    "property3": [ "==", value ]
    "property4": [ "in", [value1, value2, value3] ]
}

The default conjunction is “AND”. For instance, in the first case, the constraints will express that the command will retrieve objects where “property1” have values between [20,90], AND “property2” have a value greater or equal to “value2”, AND “property3” have a value equal to “value3”, AND “property4” is equal to either {value1, value2, value3}.

When querying for a time property, a “_date” keyword should be used following the syntax:

"time_key": ["==", {"_date": "2018-02-27T13:45:12-08:00"} ]

Tip: Given our current lack of query optimizer and as the constraints are specified as a JSON object instead of array (which leaves ordering unknown when parsing), we have introduced a way to attach monotonically increasing order from 0-n to the constraints based on user’s knowledge of which property can reduce the result set the most (see example below). When using the option of giving order to constraints, please choose the first property constraint carefully in order to restrict the most number of entity/connection returns since that one is potentially applied on an existing index. The other constraints are applied sequentially on the returned result set. If no ordering is specified, the property constraints are applied in an undetermined order.

Constraints in Add* commands

When using a constraints block in an Add* command (AddEntity, AddBoundingBox, etc), the command will become a “conditional add”. This is, the object will be inserted into the database if and only if there are no other element that fulfill the constraints. The most common use case is making sure we do not add an object twice, using some specific properties. For instance, if we want to make sure that a new object is only inserted if there is no other object with the same value for a property, we can use the constraints block as follows:

# Insert an image if and only if there is no other existing image
# with an id = 21.
"AddImage": {
    "constraints": {
        "id": [ "==", 21 ]
    },
    "properties": {
        "id": 21,
        "height": 224,
        "width":  224
    }
}

Operators for the constraints block in Add* commands are the same as for the the Find* commands.

Example

"constraints": {
    "age":        [ ">=", 20, "<=", 90 ],
    "name":       [ "in", ["Eva", "Noemi", "Tom"] ],
    "start_date": [ ">=", {"_date": "2018-02-27T13:45:12-08:00"} ]
},

Example

# Specify order in which the contraints will be applied
"constraints" : {
    "property1": [0, ">=", 25],
    "property2": [1, ">", 0.5, "<" 1.0]
}

Here the first elements in the arrays for property1 and property2 indicate the order in which those predicates should be evaluated when searching. It is important to generate these ordering indices from 0 to (#predicates - 1) in a monotonically increasing order, to avoid an error return.