Query Topics
While Sequence queries let you find recording sessions by their session-level metadata, Topic queries let you go one level deeper: you search for specific sensor channels across your entire dataset, regardless of which recording session they belong to. This is useful when you are not looking for a particular mission but for a particular kind of sensor. For example, you might want to find every IMU channel recorded through a serial interface across all sessions, perhaps to audit hardware configurations, build a training dataset for a model that requires IMU data, or check which sessions have coverage from a particular sensor type.
The QueryTopic builder works the same way as QuerySequence: each .with_*() call you chain onto it adds another AND condition, and the daemon evaluates all conditions together on the server side. Only Topics that satisfy every constraint are returned.
- Python
- C++
- Rust
The C++ SDK is currently in development.
The Rust SDK is currently in development.
Querying Topics by Type and Metadata
The key filter in a Topic query is with_ontology_tag(). Every type in Mosaico's Ontology (IMU, GPS, Pressure, String, and so on) has a unique identifier called an ontology tag. Calling IMU.ontology_tag() returns that identifier, and passing it to with_ontology_tag() tells the daemon to restrict results to Topics that carry IMU data. This is how you express "I want topics of this type" without knowing their names in advance.
You can narrow the results further by chaining with_user_metadata() calls. Metadata can be attached to Topics during ingestion, just as it can be attached to Sequences. In the example below, the query combines the IMU type filter with a metadata filter on the "interface" field, so it only returns IMU topics that were recorded through a serial interface. The AND semantics mean both conditions must hold simultaneously.
- Python
- C++
- Rust
from mosaicolabs import MosaicoClient, QueryTopic, IMU
with MosaicoClient.connect("localhost", 6726) as client:
results = client.query(
QueryTopic()
.with_ontology_tag(IMU.ontology_tag())
.with_user_metadata("interface", eq="serial")
)
if results:
for item in results:
print(f"Matched Sequence: {item.sequence.name}")
print(f" Topics: {[topic.name for topic in item.topics]}")
The C++ SDK is currently in development.
The Rust SDK is currently in development.
client.query() returns None on error, or a QueryResponse, a list of QueryResponseItem objects. The structure is the same as in a Sequence query: each item.sequence gives you the parent recording session that contains the matched topics, and item.topics gives you the specific Topics within that session that satisfied your filter. This grouping is deliberate; it lets you navigate directly from a matched Topic to the session it belongs to, so you can open a handler for either the topic or the full session depending on what you need next.
topic.name returns the relative path (e.g. /front/camera/image), directly usable with other SDK methods like topic_handler() and streamers.
Key Concepts
Ontology tags are the primary way to filter by sensor type. Each Ontology type in Mosaico carries a tag that uniquely identifies it in the catalog. Calling .ontology_tag() on a model class (for example IMU.ontology_tag()) returns the string identifier that the daemon uses internally to classify Topics. Using this tag as a filter guarantees type safety: you get back only Topics whose data actually conforms to the IMU schema, not just Topics that happen to be named /imu.
Combining filters with with_ontology_tag() and with_user_metadata() narrows results with AND semantics. Because every .with_*() call adds an additional required condition, you can compose arbitrarily specific queries. Start with a type filter to establish the sensor kind, then add metadata conditions to select by hardware variant, interface type, calibration status, or any other field you stored at ingestion time.
Generic methods using with_expression() and the .Q proxy give you access to the full operator set when the convenience methods do not cover your use case. The .Q proxy builds type-safe field paths directly from Ontology model definitions, so your queries stay consistent with the schema even as it evolves.