Find rows (C#)
Finds rows in a table using filter and sort clauses, including vector search.
For general information about working with tables and rows, see About tables with the Data API (C#).
|
Ready to write code? See the examples for this method to get started. If you are new to the Data API, check out the quickstart. |
Result
Returns a TableFindCursor object that supports fluent chaining of options to modify the Find operation.
This object implements IEnumerable and IAsyncEnumerable to iterate over the found rows.
The columns included in the returned rows depend on the subset of columns that were requested in the projection.
If requested and applicable, each row will also include a $similarity key with a numeric similarity score that represents the closeness of the sort vector and the row’s vector.
You must iterate over the cursor to fetch matching rows. For details about iteration, see Iterate over found rows.
Parameters
Use the Find method, which belongs to the Table class.
Method signature
public TableFindCursor<T> Find(TableFindOptions<T> options = null);
public TableFindCursor<T> Find(
TableFilter<T> filter, TableFindOptions<T> options = null
);
public TableFindCursor<T, TResult> Find<TResult>(
TableFindOptions<T> options = null
) where TResult : classl;
public TableFindCursor<T, TResult> Find<TResult>(
TableFilter<T> filter, TableFindOptions<T> options = null
) where TResult : class;
|
For best performance, filter and sort on indexed columns, partition keys, and clustering keys. Filtering on non-indexed columns is inefficient and resource-intensive, especially for large datasets. With the Data API clients, such operations can hit the client timeout limit before the underlying HTTP operation is complete. If you filter on non-indexed columns, the Data API will give a warning. An empty filter or omitted filter may also result in an inefficient and long-running operation. Additionally, the Data API can perform in-memory sorting, depending on the columns you sort on, the table’s partitioning structure, and whether the sorted columns are indexed. In-memory sorts can have performance implications. |
| Name | Type | Summary |
|---|---|---|
|
|
Optional. An object that defines filter criteria using the Data API filter syntax. The method only finds rows that match the filter criteria. Filters can improve performance by reducing the number of rows that the Data API processes. For a list of available filter operators and more examples, see Filter operators for tables (C#). To perform a vector search, use To avoid fetching unnecessary rows, which can contain tombstones, DataStax recommends that you use a filter that limits the number of rows scanned. For example, filter on partition key columns or indexed columns. Default: No filter For an example, see Use filters to find rows. |
|
Optional.
Options for this operation.
For more information and examples for general options such as timeout, see Customize API interaction.
For options specific to this method, see Method-specific properties of the |
| Name | Type | Summary |
|---|---|---|
|
|
Optional. Controls which columns are included or excluded in the returned rows. For more information, see Projections for tables (C#). DataStax recommends a projection to avoid unnecessarily returning large columns, such as Default: All columns For examples, see Include only specific columns in the response and Exclude specific columns from the response. |
|
|
Optional. Sorts rows by one or more columns, or performs a vector search. For more information, see Sort clauses for tables (C#). |
|
|
Optional.
Whether to include a This parameter doesn’t work with vectorize; it only works if you provide the search vector for vector search directly. Default: false For an example, see Include the similarity score with the result. |
|
|
Optional. The number of rows to bypass (skip) before returning rows. The API excludes the first This parameter only applies if you also explicitly specify an ascending or descending sort criterion. This parameter is not valid with vector search. |
|
|
Optional.
Limit the total number of rows returned.
Once For vector search, a lower limit reduces the accuracy of the search and the time required for the search. |
|
|
Optional.
The Used to manually request the next page of results. This is useful for cases where an external action triggers fetching the next page of results. For usage, see Iterate over found rows. |
Examples
The following examples demonstrate how to find rows in a table.
Use filters to find rows
You can use a filter to find rows that match specific criteria.
For example, you can find rows with an is_checked_out value of false and a number_of_pages value less than 300.
For optimal performance, you only filter on indexed columns. The Data API returns a warning if you filter on a non-indexed column.
For a list of available filter operators, see Filter operators for tables (C#).
-
Typed
-
Untyped
You can manually define a client-side type for your table to help statically catch errors. For more information and examples, see Custom typing for tables.
using System.Text.Json;
using DataStax.AstraDB.DataApi;
using DataStax.AstraDB.DataApi.Core;
using DataStax.AstraDB.DataApi.Tables;
namespace Examples;
public class Book
{
[ColumnPrimaryKey(1)]
[ColumnName("title")]
public string Title { get; set; } = null!;
[ColumnPrimaryKey(2)]
[ColumnName("author")]
public string Author { get; set; } = null!;
[ColumnName("number_of_pages")]
public int? NumberOfPages { get; set; }
[ColumnName("genres")]
public HashSet<string>? Genres { get; set; }
[ColumnName("is_checked_out")]
public bool? IsCheckedOut { get; set; }
}
public class Program
{
static async Task Main()
{
// Get an existing table
var client = new DataAPIClient();
var database = client.GetDatabase(
"API_ENDPOINT",
"APPLICATION_TOKEN"
);
var table = database.GetTable<Book>("TABLE_NAME");
// Find rows
var filterBuilder = Builders<Book>.TableFilter;
var filter = filterBuilder.And(
filterBuilder.Eq(b => b.IsCheckedOut, false),
filterBuilder.Lt(b => b.NumberOfPages, 300)
);
var results = table.Find(filter);
await foreach (var row in results)
{
Console.WriteLine(JsonSerializer.Serialize(row));
}
}
}
If you don’t pass a type parameter, the collection or table remains untyped. This is a more flexible but less type-safe option.
using System.Text.Json;
using DataStax.AstraDB.DataApi;
using DataStax.AstraDB.DataApi.Core;
using DataStax.AstraDB.DataApi.Tables;
namespace Examples;
public class Program
{
static async Task Main()
{
// Get an existing table
var client = new DataAPIClient();
var database = client.GetDatabase(
"API_ENDPOINT",
"APPLICATION_TOKEN"
);
var table = database.GetTable("TABLE_NAME");
// Find rows
var filterBuilder = Builders<Row>.TableFilter;
var filter = filterBuilder.And(
filterBuilder.Eq("is_checked_out", false),
filterBuilder.Lt("number_of_pages", 300)
);
var results = table.Find(filter);
await foreach (var row in results)
{
Console.WriteLine(JsonSerializer.Serialize(row));
}
}
}
Use vector search with a search vector to find rows
Perform a vector search by providing a search vector in the sort clause. This returns the row whose vector column value is most similar to the provided search vector.
The vector column must be indexed.
If your table has multiple vector columns, you can only sort on one vector column at a time.
The client automatically binary-encodes your search vector.
-
Typed
-
Untyped
You can manually define a client-side type for your table to help statically catch errors. For more information and examples, see Custom typing for tables.
using System.Text.Json;
using DataStax.AstraDB.DataApi;
using DataStax.AstraDB.DataApi.Core;
using DataStax.AstraDB.DataApi.Core.Query;
using DataStax.AstraDB.DataApi.Tables;
namespace Examples;
public class Book
{
[ColumnPrimaryKey(1)]
[ColumnName("title")]
public string Title { get; set; } = null!;
[ColumnPrimaryKey(2)]
[ColumnName("author")]
public string Author { get; set; } = null!;
[ColumnVector(5)]
[ColumnName("summary_genres_vector")]
public object? SummaryGenresVector { get; set; }
}
public class Program
{
static async Task Main()
{
// Get an existing table
var client = new DataAPIClient();
var database = client.GetDatabase(
"API_ENDPOINT",
"APPLICATION_TOKEN"
);
var table = database.GetTable<Book>("TABLE_NAME");
// Find rows
var embeddings = new float[] { 0.08f, -0.62f, 0.39f };
var results = table.Find(
new TableFindOptions<Book>()
{
Sort = Builders<Book>.TableSort.Vector(
b => b.SummaryGenresVector,
embeddings
),
}
);
await foreach (var row in results)
{
Console.WriteLine(JsonSerializer.Serialize(row));
}
}
}
If you don’t pass a type parameter, the collection or table remains untyped. This is a more flexible but less type-safe option.
using System.Text.Json;
using DataStax.AstraDB.DataApi;
using DataStax.AstraDB.DataApi.Core;
using DataStax.AstraDB.DataApi.Core.Query;
using DataStax.AstraDB.DataApi.Tables;
namespace Examples;
public class Program
{
static async Task Main()
{
// Get an existing table
var client = new DataAPIClient();
var database = client.GetDatabase(
"API_ENDPOINT",
"APPLICATION_TOKEN"
);
var table = database.GetTable("TABLE_NAME");
// Find rows
var embeddings = new float[] { 0.08f, -0.62f, 0.39f };
var results = table.Find(
new TableFindOptions<Row>()
{
Sort = Builders<Row>.TableSort.Vector(
"summary_genres_vector",
embeddings
),
}
);
await foreach (var row in results)
{
Console.WriteLine(JsonSerializer.Serialize(row));
}
}
}
Use vector search with a search string to find rows
Perform a vector search by providing a search string in the sort clause. The search string is converted to a search vector, and the row whose vector column value is most similar to the search vector is returned.
The vector column must have an embedding provider integration. You can configure embedding provider integrations when you create a table, add a vector column to an existing table, or alter an existing vector column. The vector column must be indexed.
If your table has multiple vector columns, you can only sort on one vector column at a time.
-
Typed
-
Untyped
You can manually define a client-side type for your table to help statically catch errors. For more information and examples, see Custom typing for tables.
using System.Text.Json;
using DataStax.AstraDB.DataApi;
using DataStax.AstraDB.DataApi.Core;
using DataStax.AstraDB.DataApi.Core.Query;
using DataStax.AstraDB.DataApi.Tables;
namespace Examples;
public class Book
{
[ColumnPrimaryKey(1)]
[ColumnName("title")]
public string Title { get; set; } = null!;
[ColumnPrimaryKey(2)]
[ColumnName("author")]
public string Author { get; set; } = null!;
[ColumnVectorize(
provider: "nvidia",
modelName: "nvidia/nv-embedqa-e5-v5",
dimension: 1024
)]
[ColumnName("summary_genres_vector")]
public object? SummaryGenresVector { get; set; }
}
public class Program
{
static async Task Main()
{
// Get an existing table
var client = new DataAPIClient();
var database = client.GetDatabase(
"API_ENDPOINT",
"APPLICATION_TOKEN"
);
var table = database.GetTable<Book>("TABLE_NAME");
// Find rows
var results = table.Find(
new TableFindOptions<Book>()
{
Sort = Builders<Book>.TableSort.Vectorize(
b => b.SummaryGenresVector,
"Text to vectorize"
),
}
);
await foreach (var row in results)
{
Console.WriteLine(JsonSerializer.Serialize(row));
}
}
}
If you don’t pass a type parameter, the collection or table remains untyped. This is a more flexible but less type-safe option.
using System.Text.Json;
using DataStax.AstraDB.DataApi;
using DataStax.AstraDB.DataApi.Core;
using DataStax.AstraDB.DataApi.Core.Query;
using DataStax.AstraDB.DataApi.Tables;
namespace Examples;
public class Program
{
static async Task Main()
{
// Get an existing table
var client = new DataAPIClient();
var database = client.GetDatabase(
"API_ENDPOINT",
"APPLICATION_TOKEN"
);
var table = database.GetTable("TABLE_NAME");
// Find rows
var results = table.Find(
new TableFindOptions<Row>()
{
Sort = Builders<Row>.TableSort.Vectorize(
"summary_genres_vector",
"Text to vectorize"
),
}
);
await foreach (var row in results)
{
Console.WriteLine(JsonSerializer.Serialize(row));
}
}
}
Use lexicographical matching to find rows
|
Lexicographical matching is currently in public preview. Development is ongoing, and the features and functionality are subject to change. Astra DB Serverless, and the use of such, is subject to the DataStax Preview Terms. |
There are two ways to use lexicographical matching to find rows with the Data API:
-
Sort to find rows with a
textorasciicolumn value that is most relevant to a given string of space-separated keywords or terms. -
Filter with the
$matchoperator to find rows with atextorasciicolumn value that is a lexicographical match to the specified string of space-separated keywords or terms
You can use these strategies together or separately.
Lexicographical matching is only available for text or ascii columns that have a text index, not a regular index.
For more information, see Create a text index (C#) and Indexes in tables (C#).
-
Typed
-
Untyped
You can manually define a client-side type for your table to help statically catch errors. For more information and examples, see Custom typing for tables.
using System.Text.Json;
using DataStax.AstraDB.DataApi;
using DataStax.AstraDB.DataApi.Core;
using DataStax.AstraDB.DataApi.Core.Query;
using DataStax.AstraDB.DataApi.Tables;
namespace Examples;
public class Book
{
[ColumnPrimaryKey(1)]
[ColumnName("title")]
public string Title { get; set; } = null!;
[ColumnPrimaryKey(2)]
[ColumnName("author")]
public string Author { get; set; } = null!;
[ColumnName("summary")]
public string Summary { get; set; } = null!;
}
public class Program
{
static async Task Main()
{
// Get an existing table
var client = new DataAPIClient();
var database = client.GetDatabase(
"API_ENDPOINT",
"APPLICATION_TOKEN"
);
var table = database.GetTable<Book>("TABLE_NAME");
// Find a row
var filterBuilder = Builders<Book>.TableFilter;
var filter = filterBuilder.LexicalMatch(
b => b.Summary,
"futuristic laboratory discovery"
);
var results = table.Find(
filter,
new TableFindOptions<Book>()
{
Sort = Builders<Book>.TableSort.Lexical(
b => b.Summary,
"futuristic laboratory"
),
}
);
await foreach (var row in results)
{
Console.WriteLine(JsonSerializer.Serialize(row));
}
}
}
If you don’t pass a type parameter, the collection or table remains untyped. This is a more flexible but less type-safe option.
using System.Text.Json;
using DataStax.AstraDB.DataApi;
using DataStax.AstraDB.DataApi.Core;
using DataStax.AstraDB.DataApi.Core.Query;
using DataStax.AstraDB.DataApi.Tables;
namespace Examples;
public class Program
{
static async Task Main()
{
// Get an existing table
var client = new DataAPIClient();
var database = client.GetDatabase(
"API_ENDPOINT",
"APPLICATION_TOKEN"
);
var table = database.GetTable("TABLE_NAME");
// Find a row
var filterBuilder = Builders<Row>.TableFilter;
var filter = filterBuilder.LexicalMatch(
"summary",
"futuristic laboratory discovery"
);
var results = table.Find(
filter,
new TableFindOptions<Row>()
{
Sort = Builders<Row>.TableSort.Lexical(
"summary",
"futuristic laboratory"
),
}
);
await foreach (var row in results)
{
Console.WriteLine(JsonSerializer.Serialize(row));
}
}
}
Use sorting to find rows
You can use a sort clause to sort rows by one or more columns.
For best performance, only sort on columns that are indexed or that are part of the primary key.
For more information, see Sort clauses for tables (C#).
-
Typed
-
Untyped
You can manually define a client-side type for your table to help statically catch errors. For more information and examples, see Custom typing for tables.
using System.Text.Json;
using DataStax.AstraDB.DataApi;
using DataStax.AstraDB.DataApi.Core;
using DataStax.AstraDB.DataApi.Core.Query;
using DataStax.AstraDB.DataApi.Tables;
namespace Examples;
public class Book
{
[ColumnPrimaryKey(1)]
[ColumnName("title")]
public string Title { get; set; } = null!;
[ColumnPrimaryKey(2)]
[ColumnName("author")]
public string Author { get; set; } = null!;
[ColumnName("rating")]
public float? Rating { get; set; }
}
public class Program
{
static async Task Main()
{
// Get an existing table
var client = new DataAPIClient();
var database = client.GetDatabase(
"API_ENDPOINT",
"APPLICATION_TOKEN"
);
var table = database.GetTable<Book>("TABLE_NAME");
// Find rows
var results = table.Find(
new TableFindOptions<Book>()
{
Sort = Builders<Book>
.TableSort.Ascending(b => b.Rating)
.Descending(b => b.Title),
}
);
await foreach (var row in results)
{
Console.WriteLine(JsonSerializer.Serialize(row));
}
}
}
If you don’t pass a type parameter, the collection or table remains untyped. This is a more flexible but less type-safe option.
using System.Text.Json;
using DataStax.AstraDB.DataApi;
using DataStax.AstraDB.DataApi.Core;
using DataStax.AstraDB.DataApi.Core.Query;
using DataStax.AstraDB.DataApi.Tables;
namespace Examples;
public class Program
{
static async Task Main()
{
// Get an existing table
var client = new DataAPIClient();
var database = client.GetDatabase(
"API_ENDPOINT",
"APPLICATION_TOKEN"
);
var table = database.GetTable("TABLE_NAME");
// Find rows
var results = table.Find(
new TableFindOptions<Row>()
{
Sort = Builders<Row>
.TableSort.Ascending("rating")
.Descending("title"),
}
);
await foreach (var row in results)
{
Console.WriteLine(JsonSerializer.Serialize(row));
}
}
}
Use an empty filter to find all rows
To find all rows, use an empty filter.
Avoid this if you have a large number of rows.
-
Typed
-
Untyped
You can manually define a client-side type for your table to help statically catch errors. For more information and examples, see Custom typing for tables.
using System.Text.Json;
using DataStax.AstraDB.DataApi;
using DataStax.AstraDB.DataApi.Tables;
namespace Examples;
public class Book
{
[ColumnPrimaryKey(1)]
[ColumnName("title")]
public string Title { get; set; } = null!;
[ColumnPrimaryKey(2)]
[ColumnName("author")]
public string Author { get; set; } = null!;
[ColumnName("number_of_pages")]
public int? NumberOfPages { get; set; }
}
public class Program
{
static async Task Main()
{
// Get an existing table
var client = new DataAPIClient();
var database = client.GetDatabase(
"API_ENDPOINT",
"APPLICATION_TOKEN"
);
var table = database.GetTable<Book>("TABLE_NAME");
// Find rows
var results = table.Find();
await foreach (var row in results)
{
Console.WriteLine(JsonSerializer.Serialize(row));
}
}
}
If you don’t pass a type parameter, the collection or table remains untyped. This is a more flexible but less type-safe option.
using System.Text.Json;
using DataStax.AstraDB.DataApi;
namespace Examples;
public class Program
{
static async Task Main()
{
// Get an existing table
var client = new DataAPIClient();
var database = client.GetDatabase(
"API_ENDPOINT",
"APPLICATION_TOKEN"
);
var table = database.GetTable("TABLE_NAME");
// Find rows
var results = table.Find();
await foreach (var row in results)
{
Console.WriteLine(JsonSerializer.Serialize(row));
}
}
}
Include the similarity score with the result
If you use a vector search to find rows, you can also include a $similarity property in the result. The $similarity value represents the closeness of the sort vector and the value of the row’s vector column.
This parameter doesn’t work with vectorize; it only works if you provide the search vector for vector search directly.
-
Typed
-
Untyped
You can manually define a client-side type for your table to help statically catch errors. For more information and examples, see Custom typing for tables.
If you use a strongly typed object for your row, you must add a property with the [DocumentMapping(DocumentMappingField.Similarity)] attribute to that object to handle receiving the similarity score.
using DataStax.AstraDB.DataApi;
using DataStax.AstraDB.DataApi.Core;
using DataStax.AstraDB.DataApi.Core.Query;
using DataStax.AstraDB.DataApi.SerDes;
using DataStax.AstraDB.DataApi.Tables;
namespace Examples;
public class Book
{
[ColumnPrimaryKey(1)]
[ColumnName("title")]
public string Title { get; set; } = null!;
[ColumnPrimaryKey(2)]
[ColumnName("author")]
public string Author { get; set; } = null!;
[ColumnVectorize(
provider: "nvidia",
modelName: "nvidia/nv-embedqa-e5-v5",
dimension: 1024
)]
[ColumnName("summary_genres_vector")]
public object? SummaryGenresVector { get; set; }
[ColumnIgnore]
[ColumnMapping(ColumnMappingField.Similarity)]
public double? Similarity { get; set; }
}
public class Program
{
static async Task Main()
{
// Get an existing table
var client = new DataAPIClient();
var database = client.GetDatabase(
"API_ENDPOINT",
"APPLICATION_TOKEN"
);
var table = database.GetTable<Book>("TABLE_NAME");
// Find rows
var results = table.Find(
new TableFindOptions<Book>()
{
Sort = Builders<Book>.TableSort.Vector(
b => b.SummaryGenresVector,
new float[] { 0.08f, -0.62f, 0.39f }
),
IncludeSimilarity = true,
}
);
await foreach (var row in results)
{
Console.WriteLine(row.Similarity);
}
}
}
If you don’t pass a type parameter, the collection or table remains untyped. This is a more flexible but less type-safe option.
using DataStax.AstraDB.DataApi;
using DataStax.AstraDB.DataApi.Core;
using DataStax.AstraDB.DataApi.Core.Query;
using DataStax.AstraDB.DataApi.Tables;
namespace Examples;
public class Program
{
static async Task Main()
{
// Get an existing table
var client = new DataAPIClient();
var database = client.GetDatabase(
"API_ENDPOINT",
"APPLICATION_TOKEN"
);
var table = database.GetTable("TABLE_NAME");
// Find rows
var results = table.Find(
new TableFindOptions<Row>()
{
Sort = Builders<Row>.TableSort.Vector(
"summary_genres_vector",
new float[] { 0.08f, -0.62f, 0.39f }
),
IncludeSimilarity = true,
}
);
await foreach (var row in results)
{
Console.WriteLine(row["$similarity"]);
}
}
}
Include only specific columns in the response
To specify which columns to include or exclude in the returned row, use a projection.
The following example demonstrates an inclusive projection.
-
Typed
-
Untyped
You can manually define a client-side type for your table to help statically catch errors. For more information and examples, see Custom typing for tables.
using System.Text.Json;
using DataStax.AstraDB.DataApi;
using DataStax.AstraDB.DataApi.Core;
using DataStax.AstraDB.DataApi.Core.Query;
using DataStax.AstraDB.DataApi.Tables;
namespace Examples;
public class Book
{
[ColumnPrimaryKey(1)]
[ColumnName("title")]
public string Title { get; set; } = null!;
[ColumnPrimaryKey(2)]
[ColumnName("author")]
public string Author { get; set; } = null!;
[ColumnName("number_of_pages")]
public int? NumberOfPages { get; set; }
[ColumnName("is_checked_out")]
public bool? IsCheckedOut { get; set; }
}
public class Program
{
static async Task Main()
{
// Get an existing table
var client = new DataAPIClient();
var database = client.GetDatabase(
"API_ENDPOINT",
"APPLICATION_TOKEN"
);
var table = database.GetTable<Book>("TABLE_NAME");
// Find rows
var projection = Builders<Book>
.Projection.Include(b => b.IsCheckedOut)
.Include(b => b.Title);
var filterBuilder = Builders<Book>.TableFilter;
var filter = filterBuilder.Lt(b => b.NumberOfPages, 300);
var results = table.Find(
filter,
new TableFindOptions<Book>() { Projection = projection }
);
await foreach (var row in results)
{
Console.WriteLine(JsonSerializer.Serialize(row));
}
}
}
If you don’t pass a type parameter, the collection or table remains untyped. This is a more flexible but less type-safe option.
using System.Text.Json;
using DataStax.AstraDB.DataApi;
using DataStax.AstraDB.DataApi.Core;
using DataStax.AstraDB.DataApi.Core.Query;
using DataStax.AstraDB.DataApi.Tables;
namespace Examples;
public class Program
{
static async Task Main()
{
// Get an existing table
var client = new DataAPIClient();
var database = client.GetDatabase(
"API_ENDPOINT",
"APPLICATION_TOKEN"
);
var table = database.GetTable("TABLE_NAME");
// Find rows
var projection = Builders<Row>
.Projection.Include("is_checked_out")
.Include("title");
var filterBuilder = Builders<Row>.TableFilter;
var filter = filterBuilder.Lt("number_of_pages", 300);
var results = table.Find(
filter,
new TableFindOptions<Row>() { Projection = projection }
);
await foreach (var row in results)
{
Console.WriteLine(JsonSerializer.Serialize(row));
}
}
}
Exclude specific columns from the response
To specify which columns to include or exclude in the returned row, use a projection.
The following example demonstrates an exclusive projection.
-
Typed
-
Untyped
You can manually define a client-side type for your table to help statically catch errors. For more information and examples, see Custom typing for tables.
using System.Text.Json;
using DataStax.AstraDB.DataApi;
using DataStax.AstraDB.DataApi.Core;
using DataStax.AstraDB.DataApi.Core.Query;
using DataStax.AstraDB.DataApi.Tables;
namespace Examples;
public class Book
{
[ColumnPrimaryKey(1)]
[ColumnName("title")]
public string Title { get; set; } = null!;
[ColumnPrimaryKey(2)]
[ColumnName("author")]
public string Author { get; set; } = null!;
[ColumnName("number_of_pages")]
public int? NumberOfPages { get; set; }
[ColumnName("is_checked_out")]
public bool? IsCheckedOut { get; set; }
}
public class Program
{
static async Task Main()
{
// Get an existing table
var client = new DataAPIClient();
var database = client.GetDatabase(
"API_ENDPOINT",
"APPLICATION_TOKEN"
);
var table = database.GetTable<Book>("TABLE_NAME");
// Find rows
var projection = Builders<Book>
.Projection.Exclude(b => b.IsCheckedOut)
.Exclude(b => b.Title);
var filterBuilder = Builders<Book>.TableFilter;
var filter = filterBuilder.And(
filterBuilder.Eq(b => b.IsCheckedOut, false),
filterBuilder.Lt(b => b.NumberOfPages, 300)
);
var results = table.Find(
filter,
new TableFindOptions<Book>() { Projection = projection }
);
await foreach (var row in results)
{
Console.WriteLine(JsonSerializer.Serialize(row));
}
}
}
If you don’t pass a type parameter, the collection or table remains untyped. This is a more flexible but less type-safe option.
using System.Text.Json;
using DataStax.AstraDB.DataApi;
using DataStax.AstraDB.DataApi.Core;
using DataStax.AstraDB.DataApi.Core.Query;
using DataStax.AstraDB.DataApi.Tables;
namespace Examples;
public class Program
{
static async Task Main()
{
// Get an existing table
var client = new DataAPIClient();
var database = client.GetDatabase(
"API_ENDPOINT",
"APPLICATION_TOKEN"
);
var table = database.GetTable("TABLE_NAME");
// Find rows
var projection = Builders<Row>
.Projection.Exclude("is_checked_out")
.Exclude("title");
var filterBuilder = Builders<Row>.TableFilter;
var filter = filterBuilder.And(
filterBuilder.Eq("is_checked_out", false),
filterBuilder.Lt("number_of_pages", 300)
);
var results = table.Find(
filter,
new TableFindOptions<Row>() { Projection = projection }
);
await foreach (var row in results)
{
Console.WriteLine(JsonSerializer.Serialize(row));
}
}
}
Limit the number of rows returned
Specify a limit to only fetch up to a certain number of rows.
-
Typed
-
Untyped
You can manually define a client-side type for your table to help statically catch errors. For more information and examples, see Custom typing for tables.
using System.Text.Json;
using DataStax.AstraDB.DataApi;
using DataStax.AstraDB.DataApi.Core;
using DataStax.AstraDB.DataApi.Core.Query;
using DataStax.AstraDB.DataApi.Tables;
namespace Examples;
public class Book
{
[ColumnPrimaryKey(1)]
[ColumnName("title")]
public string Title { get; set; } = null!;
[ColumnPrimaryKey(2)]
[ColumnName("author")]
public string Author { get; set; } = null!;
[ColumnName("number_of_pages")]
public int? NumberOfPages { get; set; }
[ColumnName("genres")]
public HashSet<string>? Genres { get; set; }
[ColumnName("is_checked_out")]
public bool? IsCheckedOut { get; set; }
}
public class Program
{
static async Task Main()
{
// Get an existing table
var client = new DataAPIClient();
var database = client.GetDatabase(
"API_ENDPOINT",
"APPLICATION_TOKEN"
);
var table = database.GetTable<Book>("TABLE_NAME");
// Find rows
var filterBuilder = Builders<Book>.TableFilter;
var filter = filterBuilder.And(
filterBuilder.Eq(b => b.IsCheckedOut, false),
filterBuilder.Lt(b => b.NumberOfPages, 300)
);
var results = table.Find(
filter,
new TableFindOptions<Book>() { Limit = 3 }
);
await foreach (var row in results)
{
Console.WriteLine(JsonSerializer.Serialize(row));
}
}
}
If you don’t pass a type parameter, the collection or table remains untyped. This is a more flexible but less type-safe option.
using System.Text.Json;
using DataStax.AstraDB.DataApi;
using DataStax.AstraDB.DataApi.Core;
using DataStax.AstraDB.DataApi.Core.Query;
using DataStax.AstraDB.DataApi.Tables;
namespace Examples;
public class Program
{
static async Task Main()
{
// Get an existing table
var client = new DataAPIClient();
var database = client.GetDatabase(
"API_ENDPOINT",
"APPLICATION_TOKEN"
);
var table = database.GetTable("TABLE_NAME");
// Find rows
var filterBuilder = Builders<Row>.TableFilter;
var filter = filterBuilder.And(
filterBuilder.Eq("is_checked_out", false),
filterBuilder.Lt("number_of_pages", 300)
);
var results = table.Find(
filter,
new TableFindOptions<Row>() { Limit = 3 }
);
await foreach (var row in results)
{
Console.WriteLine(JsonSerializer.Serialize(row));
}
}
}
Skip rows
You can specify a number of rows to skip (bypass) before returning rows.
You can only do this if your find explicitly includes an ascending or descending sort criterion.
You cannot do this in conjunction with vector search.
-
Typed
-
Untyped
You can manually define a client-side type for your table to help statically catch errors. For more information and examples, see Custom typing for tables.
using System.Text.Json;
using DataStax.AstraDB.DataApi;
using DataStax.AstraDB.DataApi.Core;
using DataStax.AstraDB.DataApi.Core.Query;
using DataStax.AstraDB.DataApi.Tables;
namespace Examples;
public class Book
{
[ColumnPrimaryKey(1)]
[ColumnName("title")]
public string Title { get; set; } = null!;
[ColumnPrimaryKey(2)]
[ColumnName("author")]
public string Author { get; set; } = null!;
[ColumnName("rating")]
public float? Rating { get; set; }
}
public class Program
{
static async Task Main()
{
// Get an existing table
var client = new DataAPIClient();
var database = client.GetDatabase(
"API_ENDPOINT",
"APPLICATION_TOKEN"
);
var table = database.GetTable<Book>("TABLE_NAME");
// Find rows
var results = table.Find(
new TableFindOptions<Book>()
{
Sort = Builders<Book>
.TableSort.Ascending(b => b.Rating)
.Descending(b => b.Title),
Skip = 5,
}
);
await foreach (var row in results)
{
Console.WriteLine(JsonSerializer.Serialize(row));
}
}
}
If you don’t pass a type parameter, the collection or table remains untyped. This is a more flexible but less type-safe option.
using System.Text.Json;
using DataStax.AstraDB.DataApi;
using DataStax.AstraDB.DataApi.Core;
using DataStax.AstraDB.DataApi.Core.Query;
using DataStax.AstraDB.DataApi.Tables;
namespace Examples;
public class Program
{
static async Task Main()
{
// Get an existing table
var client = new DataAPIClient();
var database = client.GetDatabase(
"API_ENDPOINT",
"APPLICATION_TOKEN"
);
var table = database.GetTable("TABLE_NAME");
// Find rows
var results = table.Find(
new TableFindOptions<Row>()
{
Sort = Builders<Row>
.TableSort.Ascending("rating")
.Descending("title"),
Skip = 5,
}
);
await foreach (var row in results)
{
Console.WriteLine(JsonSerializer.Serialize(row));
}
}
}
Use filter, sort, and projection together
-
Typed
-
Untyped
You can manually define a client-side type for your table to help statically catch errors. For more information and examples, see Custom typing for tables.
using System.Text.Json;
using DataStax.AstraDB.DataApi;
using DataStax.AstraDB.DataApi.Core;
using DataStax.AstraDB.DataApi.Core.Query;
using DataStax.AstraDB.DataApi.Tables;
namespace Examples;
public class Book
{
[ColumnPrimaryKey(1)]
[ColumnName("title")]
public string Title { get; set; } = null!;
[ColumnPrimaryKey(2)]
[ColumnName("author")]
public string Author { get; set; } = null!;
[ColumnName("number_of_pages")]
public int? NumberOfPages { get; set; }
[ColumnName("rating")]
public float? Rating { get; set; }
[ColumnName("is_checked_out")]
public bool? IsCheckedOut { get; set; }
}
public class Program
{
static async Task Main()
{
// Get an existing table
var client = new DataAPIClient();
var database = client.GetDatabase(
"API_ENDPOINT",
"APPLICATION_TOKEN"
);
var table = database.GetTable<Book>("TABLE_NAME");
// Find rows
var filterBuilder = Builders<Book>.TableFilter;
var filter = filterBuilder.And(
filterBuilder.Eq(b => b.IsCheckedOut, false),
filterBuilder.Lt(b => b.NumberOfPages, 300)
);
var sort = Builders<Book>
.TableSort.Ascending(b => b.Rating)
.Descending(b => b.Title);
var projection = Builders<Book>
.Projection.Include(b => b.IsCheckedOut)
.Include(b => b.Title);
var results = table.Find(
filter,
new TableFindOptions<Book>()
{
Sort = sort,
Projection = projection,
}
);
await foreach (var row in results)
{
Console.WriteLine(JsonSerializer.Serialize(row));
}
}
}
If you don’t pass a type parameter, the collection or table remains untyped. This is a more flexible but less type-safe option.
using System.Text.Json;
using DataStax.AstraDB.DataApi;
using DataStax.AstraDB.DataApi.Core;
using DataStax.AstraDB.DataApi.Core.Query;
using DataStax.AstraDB.DataApi.Tables;
namespace Examples;
public class Program
{
static async Task Main()
{
// Get an existing table
var client = new DataAPIClient();
var database = client.GetDatabase(
"API_ENDPOINT",
"APPLICATION_TOKEN"
);
var table = database.GetTable("TABLE_NAME");
// Find rows
var filterBuilder = Builders<Row>.TableFilter;
var filter = filterBuilder.And(
filterBuilder.Eq("is_checked_out", false),
filterBuilder.Lt("number_of_pages", 300)
);
var sort = Builders<Row>
.TableSort.Ascending("rating")
.Descending("title");
var projection = Builders<Row>
.Projection.Include("is_checked_out")
.Include("title");
var results = table.Find(
filter,
new TableFindOptions<Row>() { Sort = sort, Projection = projection }
);
await foreach (var row in results)
{
Console.WriteLine(JsonSerializer.Serialize(row));
}
}
}
Iterate over found rows
Use foreach to iterate over the found rows.
The Data API returns results in pages.
The TableFindCursor result handles the paging internally as part of the IEnumerable and IAsyncEnumerable implementations.
Alternatively, you can use the InitialPageState parameter to fetch a specific page of results.
This is useful for cases where an external action triggers fetching the next page of results.
For example, you might use this feature if you implement a "Load More" button or an infinite scroll interface.
If you need a list of all results, call ToList().
However, the time and memory required for this operation depend on the number of results.
This is not recommended when you expect a large number of rows.
The following example uses untyped rows, but you can use strongly-typed classes for compile-time checks and IntelliSense. For more information and examples, see Custom typing for tables.
Example using foreach:
using System.Text.Json;
using DataStax.AstraDB.DataApi;
using DataStax.AstraDB.DataApi.Core;
using DataStax.AstraDB.DataApi.Tables;
namespace Examples;
public class Program
{
static async Task Main()
{
// Get an existing table
var client = new DataAPIClient();
var database = client.GetDatabase(
"API_ENDPOINT",
"APPLICATION_TOKEN"
);
var table = database.GetTable("TABLE_NAME");
// Find rows
var filterBuilder = Builders<Row>.TableFilter;
var filter = filterBuilder.And(
filterBuilder.Eq("is_checked_out", false),
filterBuilder.Lt("number_of_pages", 300)
);
var results = table.Find(filter);
// Use foreach
await foreach (var row in results)
{
Console.WriteLine(JsonSerializer.Serialize(row));
}
}
}
Example using InitialPageState:
using System.Text.Json;
using DataStax.AstraDB.DataApi;
using DataStax.AstraDB.DataApi.Core;
using DataStax.AstraDB.DataApi.Core.Query;
using DataStax.AstraDB.DataApi.Tables;
namespace Examples;
public class Program
{
static async Task Main()
{
// Get an existing table
var client = new DataAPIClient();
var database = client.GetDatabase(
"API_ENDPOINT",
"APPLICATION_TOKEN"
);
var table = database.GetTable("TABLE_NAME");
// Create the filter
var filterBuilder = Builders<Row>.TableFilter;
var filter = filterBuilder.And(
filterBuilder.Eq("is_checked_out", false),
filterBuilder.Lt("number_of_pages", 300)
);
// Get the first page
var cursor1 = table.Find(filter);
var page1 = await cursor1.FetchNextPageAsync();
var results1 = page1.Results;
foreach (var row in results1)
{
Console.WriteLine(JsonSerializer.Serialize(row));
}
var paginationState1 = page1.NextPageState;
// Get the next page
if (paginationState1 != null)
{
var cursor2 = table.Find(
filter,
new TableFindOptions<Row>()
{
InitialPageState = paginationState1,
}
);
var page2 = await cursor2.FetchNextPageAsync();
var results2 = page2.Results;
foreach (var row in results2)
{
Console.WriteLine(JsonSerializer.Serialize(row));
}
var paginationState2 = page2.NextPageState;
}
}
}
Client reference
For more information, see the client reference.