A beginner-friendly guide to database queries
Throughout this guide, we'll use a "Users" collection with 3 documents. Understanding this data will help you follow along with all the examples.
{ "Birthday": "1990-01-01", "IsManager": true, "Name": "Bob", "Weight": 70, "Car": { "Model": "Subaru" }, "Childs": [ { "Age": 3, "Name": "Ted", "Numbers": [4, 5, 6] }, { "Age": 5, "Name": "Mike", "Numbers": [7, 8, 9] }, { "Age": 20, "Name": "Boby" } ], "Facet1": { "Attr1": false, "Attr2": true, "Attr3": false }, "Facet2": { "Attr1": false, "Attr2": true, "Attr3": false }, "Jobs": [ { "Company": "Microsoft", "Position": "Engineer" }, { "Company": "Amazon", "Position": "Manager" } ], "Numbers": [1] }
{ "Name": "Ted", "Weight": 75, "IsManager": true, "Jobs": [ { "Company": "Microsoft", "Position": "Manager" } ] }
{ "Age": 25, "Name": "Tim", "Car": { "Engine": "3.0", "Model": "VW" }, "Childs": [ { "Age": "5", "Name": "Ted" } ], "Numbers": [7, 2, 3, 7], "Participants": [ { "Choose": null, "Gender": "Boy", "Name": "Hello", "Questions": [ "Question1", "Question2", "Question3" ] } ] }
A query is a way to ask your database for information. Think of it like asking questions to your data storage.
Before you can query data, you need to specify which collection (table) you want to work with. In the new format, you pass the collection name directly to the query methods:
// Old format (deprecated) Client.SetDefaultCollection("Users") .GetDoc(1) // New format FirstDocOf("Users")
To get one specific document by its ID:
FirstDocOf("Users") .Count();
This finds the first document and counts how many were found (should be 1 if it exists).
To get a document by specific ID:
uint docID = 1; DocsWhere("Users", docID) .Count();
To get everything from a collection:
DocsOf("Users") .Count();
This returns all documents in the Users collection.
To find documents that match certain conditions, use DocsWhere:
DocsWhere("Users", new { Name = "Bob" }) .Select<UserInfo>();
This finds all users with the name "Bob".
You can filter by multiple fields at once:
DocsWhere("Users", new { Name = "Bob", Car = new { Model = "Subaru" } }) .Select<UserInfo>();
This finds users named "Bob" who have a Subaru car. All conditions must match (AND logic).
You can also write filters as JSON strings:
DocsWhere("Users", "{'Car':{'Engine':2}}") .Select<UserInfo>();
Use AndWhere and OrWhere to combine conditions:
// Find users named "Bob" AND age 20 DocsWhere("Users", "{'Name':'Bob'}") .AndWhere("{'Age':20}") .Count(); // Find users named "Bob" OR age 20 DocsWhere("Users", "{'Name':'Bob'}") .OrWhere("{'Age':20}") .Count();
You can use special operators to compare values:
| Operator | Meaning | Example |
|---|---|---|
| Less() | Less than | Age < 21 |
| LessOrEqual() | Less than or equal | Age ≤ 20 |
| Great() | Greater than | Age > 10 |
| GreatOrEqual() | Greater than or equal | Age ≥ 20 |
| Not() | Not equal to | Age ≠ 20 |
// Find users younger than 21 DocsWhere("Users", "{'Age':Less(21)}") .Select<UserInfo>(); // Result: Returns Bob (Age: 20) // Find users 20 or older DocsWhere("Users", "{'Age':GreatOrEqual(20)}") .Select<UserInfo>(); // Result: Returns Bob (Age: 20) // Find users not age 20 DocsWhere("Users", "{'Age':Not(20)}") .Select<UserInfo>(); // Result: Returns 0 documents
To find values between two numbers or dates:
// Age between 20 and 21 DocsWhere("Users", "{'Age':Range(20,21)}") .Select<UserInfo>(); // Result: Returns Bob (Age: 20) // Birthday between two dates DocsWhere("Users", "{'Birthday':Range('1980-01-01','2000-01-01')}") .Select<UserInfo>(); // Result: Returns Bob (Birthday: 1990-01-01)
Use Template() to match patterns (like wildcards):
// Find ages starting with '2' (like 20, 21, 29) DocsWhere("Users", "{'Age':Template('2*')}") .Select<UserInfo>(); // Result: Returns Bob (Age: 20)
Use Any() to check if a value matches any of several options:
// Find users with age 20 OR 21 DocsWhere("Users", "{'Age':Any(20,21)}") .Select<UserInfo>(); // Result: Returns Bob (Age: 20)
To find documents where an array contains a specific value:
// Find users who have number 2 in their Numbers array DocsWhere("Users", "{'Numbers':[2]}") .Select<UserInfo>(); // Result: Returns Bob (Numbers: [1,2,3] after updates)
Check if ALL specified values exist in the array:
// Find users who have BOTH 1 AND 2 in Numbers DocsWhere("Users", "{'Numbers':[1,2]}") .Select<UserInfo>(); // Result: Returns Bob (after updates, has [1,2,3])
Check if ANY of the specified values exist:
// Find users who have 1 OR 5 in Numbers DocsWhere("Users", "{'Numbers':[Any,1,5]}") .Select<UserInfo>(); // Result: Returns Bob (has 1 in Numbers)
Check if a value does NOT exist in the array:
// Find users who DON'T have 2 in Numbers DocsWhere("Users", "{'Numbers':[Nin,2]}") .Select<UserInfo>(); // Result: Initially returns 0, later returns Bob after 2 is deleted
You can search for objects with specific properties:
// Find users who have a child named "Ted" DocsWhere("Users", "{'Childs':[{'Name':'Ted'}]}") .Select<UserInfo>(); // Result: Returns Bob (has a child named Ted) // Find users with a Manager job position DocsWhere("Users", "{'Jobs':[{'Position':'Manager'}]}") .Select<UserInfo>(); // Result: Returns Bob (Amazon - Manager) and Ted (Microsoft - Manager)
To count how many items are in an array:
// Count how many jobs a user has FirstDocOf("Users") .Count("{'Jobs':[{'Company':$}]}"); // Result: Returns 3 (Bob has initially 2 jobs, then gets a 3rd)
To create a completely new document:
AddDoc("Users", new UserInfo { Name = "Tim" });
Use Update to add new fields:
// Add age to Tim's document ModifyDocsWhere("Users", "{'Name':'Tim'}") .Update("{'Age':15}");
To add an array of values:
ModifyDocsWhere("Users", "{'Name':'Tim'}") .Update("{'Numbers':[1,2,3]}");
To add nested objects:
ModifyDocsWhere("Users", "{'Name':'Tim'}") .Update("{'Car':{'Engine':'2.0', 'Model':'VW'}}");
To add an object as an item in an array:
ModifyDocsWhere("Users", "{'Name':'Tim'}") .Update("{'Childs':[Add,{'Name':'Ted','Age':'5'}]}");
To change the value of a field:
ModifyDocsWhere("Users", "{'Name':'Tim'}") .Update("{'Age':25}");
To update fields inside objects:
ModifyDocsWhere("Users", "{'Name':'Tim'}") .Update("{'Car':{'Engine':'3.0'}}");
You can add or subtract numbers:
// Add 1 to age ModifyDocsWhere("Users", "{'Name':'Tim'}") .Update("{'Age':Add(1)}"); // Subtract 1 from age ModifyDocsWhere("Users", "{'Name':'Tim'}") .Update("{'Age':Sub(1)}");
Use the Add operator to append items:
// Add number 4 to the Numbers array ModifyDocsWhere("Users", "{'Name':'Tim'}") .Update("{'Numbers':[Add,4]}"); // Add a new child object ModifyDocsWhere("Users", "{'Name':'Bob'}") .Update("{'Childs':[Add,{'Name':'Boby','Age':20}]}");
Use @ with an index number to update specific positions:
// Update the first item (index 0) ModifyDocsWhere("Users", "{'Name':'Tim'}") .Update("{'Numbers':[@0,7]}"); // Update the last item ModifyDocsWhere("Users", "{'Name':'Tim'}") .Update("{'Numbers':[Last,7]}");
By default, Select returns everything:
DocsWhere("Users", "{'Name':'Bob'}") .Select<UserInfo>(); // Result: Returns Bob's complete document with all fields: // Name: "Bob", Birthday: "1990-01-01", Weight: 70, // IsManager: true, Car, Childs, Jobs, Numbers, etc.
Use $ to specify which fields you want:
// Only get Car information DocsWhere("Users", "{'Name':'Bob'}") .Select<UserInfo>("{'Car':{'Engine':$,'Model':$}}"); // Result: Returns only Car data // { Car: { Engine: "2", Model: "Subaru" } } // Note: After updates, Engine will have value "2"
Use ! to extract nested objects directly:
// Get just the Car object as the result DocsWhere("Users", "{'Name':'Bob'}") .Select("{'Car':!{'Engine':$}}");
Get specific items from arrays:
// Get the second number (index 1) from Bob DocsWhere("Users", "{'Name':'Bob'}") .Select<UserInfo>("{'Numbers':[@1,$]}"); // Result: Returns [2] (Bob's second number after updates) // Get the last number DocsWhere("Users", "{'Name':'Bob'}") .Select<UserInfo>("{'Numbers':[Last,$]}"); // Result: Returns [3] (Bob's last number)
Use P (Portion) to get a slice:
// Get items from index 0 to 2 (first 2 items) DocsWhere("Users", "{'Name':'Bob'}") .Select<UserInfo>("{'Numbers':[P,0,2,$]}");
Combine filtering with the R (Result) operator:
// Get only Manager jobs DocsWhere("Users", "{'Name':'Bob','Jobs':[{'Position':'Manager'}]}") .Select<UserInfo>("{'Jobs':[R,{'Company':$,'Position':$}]}"); // Result: Returns only Bob's Manager job // Jobs: [{ Company: "Amazon", Position: "Manager" }] // (Microsoft Engineer job is filtered out)
// Count documents DocsWhere("Users", "{'Name':'Bob'}") .Count(); // Result: 1 // Sum values in an array DocsWhere("Users", "{'Name':'Bob'}") .Sum("{'Numbers':[$]}"); // Result: 6 (sum of Bob's Numbers after updates: [1,2,3])
To remove a field from a document:
// Delete the Age field DocsWhere("Users", "{'Name':'Bob'}") .Delete("{'Age':$}");
To remove fields from nested objects:
// Delete only the Engine from Car ModifyDocsWhere("Users", "{'Name':'Bob'}") .Delete("{'Car':{'Engine':$}}");
// Delete the second item (index 1) ModifyDocsWhere("Users", "{'Name':'Bob'}") .Delete("{'Numbers':[@1,$]}"); // Delete the last item ModifyDocsWhere("Users", "{'Name':'Bob'}") .Delete("{'Numbers':[Last,$]}");
Remove items that match a specific value:
// Delete the number 4 from the array DocsWhere("Users", "{'Name':'Bob'}") .Delete("{'Numbers':[4]}");
Remove objects that match certain criteria:
// Delete all jobs at Google ModifyDocsWhere("Users", "{'Name':'Bob','Jobs':[{'Company':'Google'}]}") .Delete("{'Jobs':[$]}");
To get a specific subset of results:
// Skip first document, take 1 DocsOf("Users") .Skip(1) .Take(1) .Count();
Use OrderBy to sort your results:
// Sort by Name ascending (A to Z) DocsOf("Users") .OrderBy("{'Name':$}") .Select<UserInfo>(); // Sort by Name descending (Z to A) DocsOf("Users") .OrderByDesc("{'Name':$}") .Select<UserInfo>();
You can nest AND/OR conditions:
// (IsManager = true) AND (Weight = 70 OR Weight = 75) DocsWhere("Users", "{'IsManager':true}") .AndWhere( DocsWhere("Users", "{'Weight':70}") .OrWhere("{'Weight':75}") ) .Select<UserInfo>(); // Result: Returns Ted (Weight: 75, IsManager: true)
Search using multiple categories (facets):
// Find users matching both facet filters DocsWhereFacet("Users", "{'Facet1':{'Attr1':true,'Attr2':true},'Facet2':{'Attr1':true,'Attr2':true}}") .Select<UserInfo>(); // Result: Returns Bob (when both Attr1 and Attr2 are true in facets) // Find with correct facet values DocsWhereFacet("Users", "{'Facet1':{'Attr2':true},'Facet2':{'Attr2':true}}") .Select<UserInfo>(); // Result: Returns Bob (both facets have Attr2: true)
Convert query results into a new collection:
// Extract all child objects into a new collection var coll = DocsWhere("Users", "{'Name':'Bob'}") .ToCollection("{'Childs':[!{'Name':$,'Age':$}]}");
Use Any() to check if documents exist:
// Returns true if any matching documents exist uint docID = 1; var exists = DocsWhere("Users", docID) .AndWhere("{'Jobs':[{'Company':'Microsoft'}]}") .Any();
You can pass objects as variables using @VariableName:
ModifyDocsWhere("Users", "{'Name':'Tim'}") .Update("{'Participants':[Add,@Participant]}", new Participant { Name = "Hello", Gender = GenderType.Boy, Questions = new List<string> { "Q1", "Q2" } });
You can chain multiple operations together:
// Complex query chain DocsWhere("Users", "{'Name':'Bob'}") .AndWhere("{'Age':20}") .OrWhere("{'Name':'Tim'}") .OrderBy("{'Name':$}") .Skip(0) .Take(10) .Select<UserInfo>();