Query types, indexes, and vector filtering
The runnable Python examples create small, uniquely named fixtures, assert the results below, and remove their records and property indexes. Run them against a disposable database with the aperturedb Python package installed. Supply credentials through ADB_USER and ADB_PASSWORD. For a local server without TLS:
python query_semantics.py --host 127.0.0.1 --port 55555 --no-ssl --output results.json
Omit --no-ssl when the server uses TLS. The result file contains the checked outcomes; any unexpected result or missing expected error fails the script. No existing class, property index, or descriptor set is reused. Empty fixture class definitions may remain after record cleanup.
Stored and evaluated types
A native property has one enforced physical type within a class. After storing p: 1, storing p: "1" on another record in the same class fails. A JSON property can hold differently typed payloads while retaining the JSON storage type. Its payloads 1, "1" and true remain different values.
The examples select the intended record before comparing a JSON payload:
["all", ["$rid", "==", 0], ["$p", "==", 1]]
An unguarded numeric comparison over incompatible JSON payloads raises a type error. is_missing matches both JSON null and an absent property. An explicit type index preserves these results; it indexes storage types and does not convert JSON into a native numeric or string property.
For an ordinary list request, a small limit can satisfy the page before a later row’s error is encountered. Do not use a limit to validate the entire class. An exact count requires all matches before pagination. Page-local aggregates may also encounter errors outside the returned page; see constraints for evaluation and error rules.
Precision and arrays
JSON preserves the integer 9007199254740993 for exact membership. Use an explicit JSON literal when expressing that value:
[{"json": 9007199254740993}, "in", "$j"]
The example distinguishes it from 9007199254740992 before and after array index creation. Preservation for membership does not make it a representable finite scalar number: ["$p", "is_finite"] is false for that JSON integer.
List membership means all-element containment. An empty left list is contained in every right list. ["$a", "in", {"array": [1]}] matches an empty array, but does not match [1, "1", true]. Strings and booleans are not coerced to numbers.
Text operators have different normalization
icontains applies full case folding: searching for STRASSE matches both Straße and STRASSE. iregex follows the regex engine’s case matching; ^strasse$ matches the second spelling in this fixture.
Fulltext uses compatibility normalization, so a query for abc matches both ABC and abc. Similarity does not apply that fulltext normalization; a similarity score of 1 against abc selects only the latter here. Fulltext requires a suitable fulltext index and native string values. A JSON-wrapped string remains ineligible even if an index definition exists.
Request relevance sorting explicitly when desired:
score = {"fulltext": ["$text", "abc"]}
query = [{"FindEntity": {
"with_class": "YourClass",
"constraints": [score, ">", 0],
"sort": {"expression": score, "order": "descending"},
"results": {"list": ["rid"], "expressions": {"score": score}}
}}]
Descriptor filtering and index coverage
The vector example uses a two-dimensional Flat/L2 index with two close but ineligible descriptors and two farther eligible descriptors. With k=2:
Request | Returned IDs |
|---|---|
Filter first (default), before fresh insertion |
|
|
|
Filter first, after inserting a closer eligible descriptor |
|
Same search with |
|
The example inserts the descriptor and runs both follow-up queries in one transaction to demonstrate searching before the new descriptor is indexed. knn_first may return fewer than k even when enough eligible descriptors exist. It is not interchangeable with exact search over the filtered set.
These small Flat examples establish exact outcomes. They do not establish HNSW, IVF or ACORN recall on another workload. Measure approximate recall against an exact eligible-population oracle using your dimensions, data, filters, index parameters and update pattern. See FindDescriptor for search-mode details.