Files
lancedb/docs/web/basics/query.mdx
T
Brendan Clement e20664740f docs: publish the Function pages only once Functions launch
The two Function pages declare `launch: functions`, and every other page
marks what it says about Functions, so the assembled site leaves them out
until the launch. Before it, the pages that offered Functions for Python
work point Enterprise readers at Geneva instead.

The SQL Function example now uses Arrow type names, which the server
requires, and states the 3.12 default for `python_version`.
2026-10-09 13:07:33 -07:00

97 lines
3.3 KiB
Plaintext

---
title: "Queries"
sidebarTitle: "Query"
description: "Running a query, and reading its results before it finishes."
icon: magnifying-glass
keywords: ["query", "async", "streaming", "arrow", "reader", "execute_query"]
---
A query returns rows. How you get them depends on two choices that are easy to
conflate: whether **your thread** blocks, and whether you take the results all
at once or stream them as they arrive.
## Blocking or not is a language concern {#async-client}
A concern of your language, not of LanceDB. The work is identical either way.
<CodeGroup>
```python Python icon="python"
db = lancedb.connect("db://my-db", api_key="...") # blocking
tbl = db.open_table("documents")
db = await lancedb.connect_async("db://my-db", api_key="...") # coroutines
tbl = await db.open_table("documents")
```
```typescript TypeScript icon="square-js"
// TypeScript is async throughout; there is no blocking form.
const db = await lancedb.connect("db://my-db", { apiKey: "..." });
const tbl = await db.openTable("documents");
```
</CodeGroup>
Python offers both. `AsyncConnection` exposes the same surface as coroutines, so
choosing between them is about the program you are writing -- a service wants
the async form, a script does not care.
## Reading before the query finishes {#queries}
A query is not a job, but it has the same shape of choice: wait for everything,
or take a handle and start reading.
<CodeGroup>
```python Python icon="python"
reader = db.execute_query("SELECT id, text FROM my_docs LIMIT 1000")
table = reader.read_all()
query = db.execute_query_async("SELECT id, text FROM my_docs")
```
```sql SQL
SELECT id, text FROM my_docs LIMIT 1000
```
</CodeGroup>
`execute_query` returns a blocking Arrow reader **once results start arriving**
-- it does not wait for the whole query to finish. Results stream as record
batches, so a large result set does not have to fit in memory before you see its
first row.
`execute_query_async` returns the query handle instead:
```python
query = db.execute_query_async("SELECT id, text FROM my_docs")
query.id # identifies it on the server
query.describe() # what it is doing, without consuming results
reader = query.reader() # stream the rows when you want them
query.cancel() # stop it
```
`describe_query(id)` reports on one from elsewhere, the way `open_job(id)` does
for a job.
<Note>
SQL requires a deployment. See [SQL](/basics/sql#sql-is-remote).
</Note>
Query-builder searches -- vector, full-text, hybrid -- are ordinary calls that
return results. They are fast enough not to need a handle. See
[Query](/search).
## Searches are ordinary calls {#searches}
Query-builder searches -- [vector](/search/vector-search),
[full-text](/search/full-text-search), [hybrid](/search/hybrid-search) -- return
results directly. They are fast enough not to need a handle. In SQL on a
deployment, full-text search is the [`fts()`](/sql/functions#fts) table
function and vector search [depends on the deployment](/basics/sql#no-vector-sql);
hybrid search has no SQL form. See [Semantic Search](/search).
## When the work outlives the call {#jobs}
Some operations take longer than a query should: building an index, or
refreshing a computed column. Those return a **job** rather than
rows, and a job is a different handle with a different shape. See
[Jobs](/basics/jobs).