Scan & Query
Clustron DKV allows you to work with datasets, not just individual keys.
To use querying effectively, you must understand:
Entity β Labels β Indexing β Search
Search is not automatic β it is enabled through entities and labels.
Why This Mattersβ
Basic operations require exact keys:
await client.GetAsync("user:1");
But real applications need:
- Find all customers in London
- Get users with age between 28β32
- Retrieve top 5 records by age
To support this, Clustron provides:
- Scan β iterate over data
- Search β query indexed data
Entities & Labels (Foundation of Search)β
Search works on indexed metadata, not raw values.
What is an Entity?β
An entity defines a logical type of data.
Customer
Order
Session
It groups and indexes related data.
What are Labels?β
Labels are indexed fields attached to a key.
They enable:
- Filtering
- Sorting
- Aggregation
- Querying
Storing Data with Labelsβ
You must attach labels when storing data.
var putOpts = Put.WithEntity("customer")
.WithLabel("city", "London")
.WithLabel("age", "30")
.WithLabel("email", "user1@example.com");
await client.PutAsync("cust:1", customer, putOpts);
π Without labels, search cannot work efficiently.
Scan (No Index Required)β
Scan allows you to iterate over data.
await foreach (var item in client.Scan.ScanAsync(prefix: "cust:"))
{
Console.WriteLine(item.Key);
}
Characteristicsβ
- No labels required
- Streams results
- Sequential scan
Search (Requires Labels)β
Search uses indexed labels for efficient querying.
Equality Queryβ
var query = SearchQuery
.For("customer")
.Eq("city", "London");
Range Queryβ
var query = SearchQuery
.For("customer")
.Range("age", 28, 32);
Prefix Queryβ
var query = SearchQuery
.For("customer")
.LikePrefix("email", "user1");
Logical Queriesβ
ANDβ
var query = SearchQuery
.For("customer")
.And(
new EqClause("city", "Berlin"),
new EqClause("age", "32"));
ORβ
var query = SearchQuery
.For("customer")
.Or(
new EqClause("city", "Lahore"),
new EqClause("age", "25"));
NOTβ
var query = SearchQuery
.For("customer")
.Not(new EqClause("city", "Lahore"));
Combined Conditionsβ
var query = new SearchQuery("customer", new IClause[]
{
new AndClause(new List<IClause>
{
new RangeClause("age", 20, 65),
new NotClause(new EqClause("city", "Lahore"))
})
});
Sorting & Limitingβ
var query = SearchQuery
.For("customer")
.OrderBy("age", ascending: false)
.Limit(5);
Multi-field Sortingβ
var query = SearchQuery
.For("customer")
.OrderBy("city", ascending: true)
.OrderBy("age", ascending: true)
.Limit(10);
Result Shapesβ
Search results are streamed and can be consumed in different forms.
Keys Onlyβ
await using var reader =
await (await client.Scan.SearchAsync(query)).AsKeys();
Full Entries (with Metadata)β
await using var reader =
await (await client.Scan.SearchAsync(query)).AsEntries();
while (await reader.ReadAsync())
{
var labels = reader.Current.Metadata.Labels;
Console.WriteLine(labels["city"].Value);
}
Strongly Typed Entitiesβ
await using var reader =
await (await client.Scan.SearchAsync(query))
.AsEntities<Customer>();
Projection (Selected Fields)β
var query = SearchQuery
.For("customer")
.Eq("city", "New York")
.Select("email");
await using var reader =
await (await client.Scan.SearchAsync(query))
.Select(new[] { "email" });
Pagingβ
Search results are paged internally.
var opts = new SearchOptions
{
PageSize = 100
};
await client.Scan.SearchAsync(query, opts);
Paging ensures efficient processing of large datasets.
Streaming Modelβ
All results are streamed:
- Incremental processing
- Low memory usage
- Suitable for large datasets
Scan vs Searchβ
| Feature | Scan | Search |
|---|---|---|
| Requires labels | No | Yes |
| Performance | Sequential | Indexed |
| Use case | Iteration | Filtering & querying |
When to Use Whatβ
-
Use Scan when:
- You donβt have labels
- You need simple iteration
-
Use Search when:
- You need filtering
- You want performance
- You have labeled/indexed data
Best Practicesβ
- Always define an entity for structured data
- Add labels for all searchable fields
- Use search instead of scan in production
- Use paging (
SearchOptions) for large datasets - Choose appropriate result shape (
AsKeys,AsEntries, etc.) - Use projection to reduce payload size
- Combine clauses for precise filtering
Key Takeawayβ
Entity + Labels β Index β Search β Fast queries
Search is only as powerful as your labeling strategy.
Whatβs Nextβ
π Continue to Transactions for consistent grouped operations