Add subsection about stable ordering to pagination section (#2463)

* Add 'Stable Ordering' section to 'Pagination' section

* Add FAQ entry

* Small edits to the Pagination section

* Apply title case to all headers on page

* Small edit
This commit is contained in:
Abdon Pijpelink
2026-06-30 13:07:43 +02:00
committed by GitHub
parent 708c40573d
commit cf4119fa3f
42 changed files with 526 additions and 43 deletions
@@ -0,0 +1 @@
This code snippet demonstrates how to run an exact nearest neighbor search by setting the `exact` parameter to `true`. Unlike the default approximate HNSW search, exact search scans all vectors and returns results in a stable, deterministic order.
@@ -0,0 +1,17 @@
using Qdrant.Client;
using Qdrant.Client.Grpc;
public class Snippet
{
public static async Task Run()
{
var client = new QdrantClient("localhost", 6334); // @hide
await client.QueryAsync(
collectionName: "{collection_name}",
query: new float[] { 0.2f, 0.1f, 0.9f, 0.7f },
searchParams: new SearchParams { Exact = true },
limit: 10
);
}
}
@@ -0,0 +1,11 @@
```csharp
using Qdrant.Client;
using Qdrant.Client.Grpc;
await client.QueryAsync(
collectionName: "{collection_name}",
query: new float[] { 0.2f, 0.1f, 0.9f, 0.7f },
searchParams: new SearchParams { Exact = true },
limit: 10
);
```
@@ -0,0 +1,15 @@
```go
import (
"context"
"github.com/qdrant/go-client/qdrant"
)
client.Query(context.Background(), &qdrant.QueryPoints{
CollectionName: "{collection_name}",
Query: qdrant.NewQuery(0.2, 0.1, 0.9, 0.7),
Params: &qdrant.SearchParams{
Exact: qdrant.PtrOf(true),
},
})
```
@@ -0,0 +1,17 @@
```java
import static io.qdrant.client.QueryFactory.nearest;
import io.qdrant.client.QdrantClient;
import io.qdrant.client.QdrantGrpcClient;
import io.qdrant.client.grpc.Points.QueryPoints;
import io.qdrant.client.grpc.Points.SearchParams;
client.queryAsync(
QueryPoints.newBuilder()
.setCollectionName("{collection_name}")
.setQuery(nearest(0.2f, 0.1f, 0.9f, 0.7f))
.setParams(SearchParams.newBuilder().setExact(true).build())
.setLimit(10)
.build())
.get();
```
@@ -0,0 +1,10 @@
```python
from qdrant_client import QdrantClient, models
client.query_points(
collection_name="{collection_name}",
query=[0.2, 0.1, 0.9, 0.7],
search_params=models.SearchParams(exact=True),
limit=10,
)
```
@@ -0,0 +1,13 @@
```rust
use qdrant_client::qdrant::{QueryPointsBuilder, SearchParamsBuilder};
use qdrant_client::Qdrant;
client
.query(
QueryPointsBuilder::new("{collection_name}")
.query(vec![0.2, 0.1, 0.9, 0.7])
.limit(10)
.params(SearchParamsBuilder::default().exact(true)),
)
.await?;
```
@@ -0,0 +1,9 @@
```typescript
client.query("{collection_name}", {
query: [0.2, 0.1, 0.9, 0.7],
params: {
exact: true,
},
limit: 10,
});
```
@@ -0,0 +1,26 @@
package snippet
import (
"context"
"github.com/qdrant/go-client/qdrant"
)
func Main() {
// @hide-start
client, err := qdrant.NewClient(&qdrant.Config{
Host: "localhost",
Port: 6334,
})
if err != nil { panic(err) }
// @hide-end
client.Query(context.Background(), &qdrant.QueryPoints{
CollectionName: "{collection_name}",
Query: qdrant.NewQuery(0.2, 0.1, 0.9, 0.7),
Params: &qdrant.SearchParams{
Exact: qdrant.PtrOf(true),
},
})
}
@@ -0,0 +1,10 @@
```http
POST /collections/{collection_name}/points/query
{
"query": [0.2, 0.1, 0.9, 0.7],
"params": {
"exact": true
},
"limit": 10
}
```
@@ -0,0 +1,26 @@
package com.example.snippets_amalgamation;
import static io.qdrant.client.QueryFactory.nearest;
import io.qdrant.client.QdrantClient;
import io.qdrant.client.QdrantGrpcClient;
import io.qdrant.client.grpc.Points.QueryPoints;
import io.qdrant.client.grpc.Points.SearchParams;
public class Snippet {
public static void run() throws Exception {
// @hide-start
QdrantClient client =
new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build());
// @hide-end
client.queryAsync(
QueryPoints.newBuilder()
.setCollectionName("{collection_name}")
.setQuery(nearest(0.2f, 0.1f, 0.9f, 0.7f))
.setParams(SearchParams.newBuilder().setExact(true).build())
.setLimit(10)
.build())
.get();
}
}
@@ -0,0 +1,10 @@
from qdrant_client import QdrantClient, models
client = QdrantClient(url="http://localhost:6333") # @hide
client.query_points(
collection_name="{collection_name}",
query=[0.2, 0.1, 0.9, 0.7],
search_params=models.SearchParams(exact=True),
limit=10,
)
@@ -0,0 +1,17 @@
use qdrant_client::qdrant::{QueryPointsBuilder, SearchParamsBuilder};
use qdrant_client::Qdrant;
pub async fn main() -> anyhow::Result<()> {
let client = Qdrant::from_url("http://localhost:6334").build()?; // @hide
client
.query(
QueryPointsBuilder::new("{collection_name}")
.query(vec![0.2, 0.1, 0.9, 0.7])
.limit(10)
.params(SearchParamsBuilder::default().exact(true)),
)
.await?;
Ok(())
}
@@ -0,0 +1,11 @@
import { QdrantClient } from "@qdrant/js-client-rest"; // @hide
const client = new QdrantClient({ host: "localhost", port: 6333 }); // @hide
client.query("{collection_name}", {
query: [0.2, 0.1, 0.9, 0.7],
params: {
exact: true,
},
limit: 10,
});
@@ -0,0 +1 @@
This code snippet demonstrates how to paginate search results without duplicate points. By collecting the point IDs returned on each page and passing them to a `must_not: has_id` filter on the next request, each subsequent page excludes all previously seen results.
@@ -0,0 +1,20 @@
using Qdrant.Client;
using static Qdrant.Client.Grpc.Conditions;
public class Snippet
{
public static async Task Run()
{
var client = new QdrantClient("localhost", 6334); // @hide
ulong[] seenIds = [83461, 19284, 57392, 44017, 91825]; // IDs returned on previous pages
// The ! operator negates the condition (must not)
await client.QueryAsync(
collectionName: "{collection_name}",
query: new float[] { 0.2f, 0.1f, 0.9f, 0.7f },
filter: !HasId(seenIds),
limit: 5
);
}
}
@@ -0,0 +1,14 @@
```csharp
using Qdrant.Client;
using static Qdrant.Client.Grpc.Conditions;
ulong[] seenIds = [83461, 19284, 57392, 44017, 91825]; // IDs returned on previous pages
// The ! operator negates the condition (must not)
await client.QueryAsync(
collectionName: "{collection_name}",
query: new float[] { 0.2f, 0.1f, 0.9f, 0.7f },
filter: !HasId(seenIds),
limit: 5
);
```
@@ -0,0 +1,25 @@
```go
import (
"context"
"github.com/qdrant/go-client/qdrant"
)
seenIds := []uint64{83461, 19284, 57392, 44017, 91825} // IDs returned on previous pages
pointIds := make([]*qdrant.PointId, len(seenIds))
for i, id := range seenIds {
pointIds[i] = qdrant.NewIDNum(id)
}
client.Query(context.Background(), &qdrant.QueryPoints{
CollectionName: "{collection_name}",
Query: qdrant.NewQuery(0.2, 0.1, 0.9, 0.7),
Filter: &qdrant.Filter{
MustNot: []*qdrant.Condition{
qdrant.NewHasID(pointIds...),
},
},
Limit: qdrant.PtrOf(uint64(5)),
})
```
@@ -0,0 +1,25 @@
```java
import static io.qdrant.client.ConditionFactory.hasId;
import static io.qdrant.client.PointIdFactory.id;
import static io.qdrant.client.QueryFactory.nearest;
import io.qdrant.client.QdrantClient;
import io.qdrant.client.QdrantGrpcClient;
import io.qdrant.client.grpc.Common.Filter;
import io.qdrant.client.grpc.Points.QueryPoints;
import java.util.List;
var seenIds = List.of(id(83461), id(19284), id(57392), id(44017), id(91825)); // IDs returned on previous pages
client.queryAsync(
QueryPoints.newBuilder()
.setCollectionName("{collection_name}")
.setQuery(nearest(0.2f, 0.1f, 0.9f, 0.7f))
.setFilter(
Filter.newBuilder()
.addMustNot(hasId(seenIds))
.build())
.setLimit(5)
.build())
.get();
```
@@ -0,0 +1,18 @@
```python
from uuid import UUID
from qdrant_client import QdrantClient, models
seen_ids: list[int | str | UUID] = [83461, 19284, 57392, 44017, 91825] # IDs returned on previous pages
client.query_points(
collection_name="{collection_name}",
query=[0.2, 0.1, 0.9, 0.7],
query_filter=models.Filter(
must_not=[
models.HasIdCondition(has_id=seen_ids),
]
),
limit=5,
)
```
@@ -0,0 +1,15 @@
```rust
use qdrant_client::qdrant::{Condition, Filter, QueryPointsBuilder};
use qdrant_client::Qdrant;
let seen_ids = vec![83461u64, 19284, 57392, 44017, 91825]; // IDs returned on previous pages
client
.query(
QueryPointsBuilder::new("{collection_name}")
.query(vec![0.2, 0.1, 0.9, 0.7])
.filter(Filter::must_not([Condition::has_id(seen_ids)]))
.limit(5),
)
.await?;
```
@@ -0,0 +1,15 @@
```typescript
const seenIds = [83461, 19284, 57392, 44017, 91825]; // IDs returned on previous pages
client.query("{collection_name}", {
query: [0.2, 0.1, 0.9, 0.7],
filter: {
must_not: [
{
has_id: seenIds,
},
],
},
limit: 5,
});
```
@@ -0,0 +1,36 @@
package snippet
import (
"context"
"github.com/qdrant/go-client/qdrant"
)
func Main() {
// @hide-start
client, err := qdrant.NewClient(&qdrant.Config{
Host: "localhost",
Port: 6334,
})
if err != nil { panic(err) }
// @hide-end
seenIds := []uint64{83461, 19284, 57392, 44017, 91825} // IDs returned on previous pages
pointIds := make([]*qdrant.PointId, len(seenIds))
for i, id := range seenIds {
pointIds[i] = qdrant.NewIDNum(id)
}
client.Query(context.Background(), &qdrant.QueryPoints{
CollectionName: "{collection_name}",
Query: qdrant.NewQuery(0.2, 0.1, 0.9, 0.7),
Filter: &qdrant.Filter{
MustNot: []*qdrant.Condition{
qdrant.NewHasID(pointIds...),
},
},
Limit: qdrant.PtrOf(uint64(5)),
})
}
@@ -0,0 +1,12 @@
```http
POST /collections/{collection_name}/points/query
{
"query": [0.2, 0.1, 0.9, 0.7],
"filter": {
"must_not": [
{ "has_id": [83461, 19284, 57392, 44017, 91825] }
]
},
"limit": 5
}
```
@@ -0,0 +1,34 @@
package com.example.snippets_amalgamation;
import static io.qdrant.client.ConditionFactory.hasId;
import static io.qdrant.client.PointIdFactory.id;
import static io.qdrant.client.QueryFactory.nearest;
import io.qdrant.client.QdrantClient;
import io.qdrant.client.QdrantGrpcClient;
import io.qdrant.client.grpc.Common.Filter;
import io.qdrant.client.grpc.Points.QueryPoints;
import java.util.List;
public class Snippet {
public static void run() throws Exception {
// @hide-start
QdrantClient client =
new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build());
// @hide-end
var seenIds = List.of(id(83461), id(19284), id(57392), id(44017), id(91825)); // IDs returned on previous pages
client.queryAsync(
QueryPoints.newBuilder()
.setCollectionName("{collection_name}")
.setQuery(nearest(0.2f, 0.1f, 0.9f, 0.7f))
.setFilter(
Filter.newBuilder()
.addMustNot(hasId(seenIds))
.build())
.setLimit(5)
.build())
.get();
}
}
@@ -0,0 +1,18 @@
from uuid import UUID
from qdrant_client import QdrantClient, models
client = QdrantClient(url="http://localhost:6333") # @hide
seen_ids: list[int | str | UUID] = [83461, 19284, 57392, 44017, 91825] # IDs returned on previous pages
client.query_points(
collection_name="{collection_name}",
query=[0.2, 0.1, 0.9, 0.7],
query_filter=models.Filter(
must_not=[
models.HasIdCondition(has_id=seen_ids),
]
),
limit=5,
)
@@ -0,0 +1,19 @@
use qdrant_client::qdrant::{Condition, Filter, QueryPointsBuilder};
use qdrant_client::Qdrant;
pub async fn main() -> anyhow::Result<()> {
let client = Qdrant::from_url("http://localhost:6334").build()?; // @hide
let seen_ids = vec![83461u64, 19284, 57392, 44017, 91825]; // IDs returned on previous pages
client
.query(
QueryPointsBuilder::new("{collection_name}")
.query(vec![0.2, 0.1, 0.9, 0.7])
.filter(Filter::must_not([Condition::has_id(seen_ids)]))
.limit(5),
)
.await?;
Ok(())
}
@@ -0,0 +1,17 @@
import { QdrantClient } from "@qdrant/js-client-rest"; // @hide
const client = new QdrantClient({ host: "localhost", port: 6333 }); // @hide
const seenIds = [83461, 19284, 57392, 44017, 91825]; // IDs returned on previous pages
client.query("{collection_name}", {
query: [0.2, 0.1, 0.9, 0.7],
filter: {
must_not: [
{
has_id: seenIds,
},
],
},
limit: 5,
});
@@ -1,10 +1,10 @@
using Qdrant.Client;
using Qdrant.Client; // @hide
public class Snippet
{
public static async Task Run()
{
var client = new QdrantClient("localhost", 6334);
var client = new QdrantClient("localhost", 6334); // @hide
await client.QueryAsync(
collectionName: "{collection_name}",
@@ -1,8 +1,4 @@
```csharp
using Qdrant.Client;
var client = new QdrantClient("localhost", 6334);
await client.QueryAsync(
collectionName: "{collection_name}",
query: new float[] { 0.2f, 0.1f, 0.9f, 0.7f },
@@ -5,16 +5,12 @@ import (
"github.com/qdrant/go-client/qdrant"
)
client, err := qdrant.NewClient(&qdrant.Config{
Host: "localhost",
Port: 6334,
})
client.Query(context.Background(), &qdrant.QueryPoints{
CollectionName: "{collection_name}",
Query: qdrant.NewQuery(0.2, 0.1, 0.9, 0.7),
WithPayload: qdrant.NewWithPayload(true),
WithVectors: qdrant.NewWithVectors(true),
Limit: qdrant.PtrOf(uint64(10)),
Offset: qdrant.PtrOf(uint64(100)),
})
```
@@ -8,9 +8,6 @@ import io.qdrant.client.WithVectorsSelectorFactory;
import io.qdrant.client.grpc.Points.QueryPoints;
import java.util.List;
QdrantClient client =
new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build());
client.queryAsync(
QueryPoints.newBuilder()
.setCollectionName("{collection_name}")
@@ -1,8 +1,4 @@
```python
from qdrant_client import QdrantClient
client = QdrantClient(url="http://localhost:6333")
client.query_points(
collection_name="{collection_name}",
query=[0.2, 0.1, 0.9, 0.7],
@@ -2,8 +2,6 @@
use qdrant_client::qdrant::QueryPointsBuilder;
use qdrant_client::Qdrant;
let client = Qdrant::from_url("http://localhost:6334").build()?;
client
.query(
QueryPointsBuilder::new("{collection_name}")
@@ -1,8 +1,4 @@
```typescript
import { QdrantClient } from "@qdrant/js-client-rest";
const client = new QdrantClient({ host: "localhost", port: 6333 });
client.query("{collection_name}", {
query: [0.2, 0.1, 0.9, 0.7],
with_vector: true,
@@ -7,18 +7,21 @@ import (
)
func Main() {
// @hide-start
client, err := qdrant.NewClient(&qdrant.Config{
Host: "localhost",
Port: 6334,
})
if err != nil { panic(err) } // @hide
if err != nil { panic(err) }
// @hide-end
client.Query(context.Background(), &qdrant.QueryPoints{
CollectionName: "{collection_name}",
Query: qdrant.NewQuery(0.2, 0.1, 0.9, 0.7),
WithPayload: qdrant.NewWithPayload(true),
WithVectors: qdrant.NewWithVectors(true),
Limit: qdrant.PtrOf(uint64(10)),
Offset: qdrant.PtrOf(uint64(100)),
})
}
@@ -11,8 +11,10 @@ import java.util.List;
public class Snippet {
public static void run() throws Exception {
// @hide-start
QdrantClient client =
new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build());
// @hide-end
client.queryAsync(
QueryPoints.newBuilder()
@@ -1,6 +1,6 @@
from qdrant_client import QdrantClient
from qdrant_client import QdrantClient # @hide
client = QdrantClient(url="http://localhost:6333")
client = QdrantClient(url="http://localhost:6333") # @hide
client.query_points(
collection_name="{collection_name}",
@@ -2,7 +2,7 @@ use qdrant_client::qdrant::QueryPointsBuilder;
use qdrant_client::Qdrant;
pub async fn main() -> anyhow::Result<()> {
let client = Qdrant::from_url("http://localhost:6334").build()?;
let client = Qdrant::from_url("http://localhost:6334").build()?; // @hide
client
.query(
@@ -1,6 +1,6 @@
import { QdrantClient } from "@qdrant/js-client-rest";
import { QdrantClient } from "@qdrant/js-client-rest"; // @hide
const client = new QdrantClient({ host: "localhost", port: 6333 });
const client = new QdrantClient({ host: "localhost", port: 6333 }); // @hide
client.query("{collection_name}", {
query: [0.2, 0.1, 0.9, 0.7],