Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 116 additions & 0 deletions _includes/code/howto/search.profile.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
// How-to: Search -> Query profiling - TypeScript examples
import assert from 'assert';

import weaviate from 'weaviate-client';

const client = await weaviate.connectToLocal();

// Setup: create a small Article collection so the snippets below have data
await client.collections.delete('Article');
await client.collections.create({
name: 'Article',
properties: [
{ name: 'title', dataType: 'text' as const },
],
vectorizers: weaviate.configure.vectors.selfProvided(),
});

const setupCol = client.collections.use('Article');
for (let i = 0; i < 5; i++) {
await setupCol.data.insert({
properties: { title: `machine learning article ${i}` },
vectors: Array(8).fill(0).map((_, j) => (i + j) * 0.01),
});
}

// Wait for ASYNC_INDEXING to build the HNSW graph; without this the first
// nearVector call returns zero results and the server skips populating
// queryProfile.
await new Promise((resolve) => setTimeout(resolve, 3000));

// START ProfileNearVector
const collection = client.collections.use('Article');

const nvResponse = await collection.query.nearVector([0.1, 0.2, 0.3, 0.0, 0.0, 0.0, 0.0, 0.0], {
limit: 5,
// highlight-start
returnMetadata: ['queryProfile', 'distance'],
// highlight-end
});

if (nvResponse.queryProfile) {
for (const shard of nvResponse.queryProfile.shards) {
console.log(`Shard: ${shard.name} (node: ${shard.node})`);
for (const [searchType, profile] of Object.entries(shard.searches)) {
console.log(` [${searchType}]`);
for (const [key, value] of Object.entries(profile.details)) {
console.log(` ${key}: ${value}`);
}
}
}
}
// END ProfileNearVector

assert.ok(nvResponse.queryProfile, 'queryProfile should be returned for nearVector');
assert.ok(Array.isArray(nvResponse.queryProfile.shards) && nvResponse.queryProfile.shards.length > 0,
'queryProfile should contain at least one shard');

// START ProfileBM25
const bm25Response = await collection.query.bm25('machine learning', {
// highlight-start
returnMetadata: ['queryProfile', 'score'],
// highlight-end
});

if (bm25Response.queryProfile) {
for (const shard of bm25Response.queryProfile.shards) {
console.log(`Shard: ${shard.name} (node: ${shard.node})`);
for (const [searchType, profile] of Object.entries(shard.searches)) {
console.log(` [${searchType}]`);
for (const [key, value] of Object.entries(profile.details)) {
console.log(` ${key}: ${value}`);
}
}
}
}
// END ProfileBM25

assert.ok(bm25Response.queryProfile, 'queryProfile should be returned for bm25');

// START ProfileHybrid
const hybridResponse = await collection.query.hybrid('machine learning', {
// highlight-start
returnMetadata: ['queryProfile'],
// highlight-end
vector: [0.1, 0.2, 0.3, 0.0, 0.0, 0.0, 0.0, 0.0],
limit: 5,
});

if (hybridResponse.queryProfile) {
for (const shard of hybridResponse.queryProfile.shards) {
console.log(`Shard: ${shard.name} (node: ${shard.node})`);
for (const [searchType, profile] of Object.entries(shard.searches)) {
console.log(` [${searchType}]`);
for (const [key, value] of Object.entries(profile.details)) {
console.log(` ${key}: ${value}`);
}
}
}
}
// END ProfileHybrid

assert.ok(hybridResponse.queryProfile, 'queryProfile should be returned for hybrid');

// START ProfileMetadataList
// You can also request profiling alongside other metadata fields.
const listResponse = await collection.query.nearVector([0.1, 0.2, 0.3, 0.0, 0.0, 0.0, 0.0, 0.0], {
limit: 5,
returnMetadata: ['queryProfile', 'distance'],
});
// END ProfileMetadataList

assert.ok(listResponse.queryProfile);

// Cleanup
await client.collections.delete('Article');
await client.close();
2 changes: 1 addition & 1 deletion _includes/code/java-v6/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
<dependency>
<groupId>io.weaviate</groupId>
<artifactId>client6</artifactId>
<version>6.2.0</version>
<version>6.2.1-SNAPSHOT</version>
</dependency>

<!-- JUnit 5 for testing -->
Expand Down
142 changes: 142 additions & 0 deletions _includes/code/java-v6/src/test/java/SearchProfileTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import io.weaviate.client6.v1.api.WeaviateClient;
import io.weaviate.client6.v1.api.collections.CollectionHandle;
import io.weaviate.client6.v1.api.collections.Property;
import io.weaviate.client6.v1.api.collections.VectorConfig;
import io.weaviate.client6.v1.api.collections.Vectors;
import io.weaviate.client6.v1.api.collections.WeaviateObject;
import io.weaviate.client6.v1.api.collections.query.Metadata;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import static org.assertj.core.api.Assertions.assertThat;

class SearchProfileTest {

private static WeaviateClient client;
private static final String COLLECTION = "Article";

@BeforeAll
public static void beforeAll() throws IOException, InterruptedException {
client = WeaviateClient.connectToLocal();
client.collections.delete(COLLECTION);

client.collections.create(COLLECTION, c -> c
.properties(Property.text("title"))
.vectorConfig(VectorConfig.selfProvided()));

CollectionHandle<Map<String, Object>> articles =
client.collections.use(COLLECTION);

// Insert a few objects with self-provided vectors so vector search works.
String[] titles = {"machine learning", "deep neural networks",
"natural language processing", "computer vision",
"reinforcement learning"};
List<WeaviateObject<Map<String, Object>>> objs = new ArrayList<>();
for (int i = 0; i < titles.length; i++) {
float[] v = new float[]{0.1f * (i + 1), 0.2f * (i + 1), 0.3f * (i + 1)};
Map<String, Object> props = Map.of("title", titles[i]);
objs.add(WeaviateObject.of(b -> b
.uuid(UUID.randomUUID().toString())
.properties(props)
.vectors(Vectors.of(v))));
}
articles.data.insertMany(objs);

// ASYNC_INDEXING is enabled on the test instance; the HNSW graph isn't
// queryable immediately after insert, so the first near_vector call would
// return zero results and the server would skip populating queryProfile.
Thread.sleep(3000);
}

@AfterAll
public static void afterAll() throws Exception {
if (client != null) {
client.collections.delete(COLLECTION);
client.close();
}
}

@Test
void testProfileNearVector() {
// START ProfileNearVector
CollectionHandle<Map<String, Object>> collection =
client.collections.use(COLLECTION);

var response = collection.query.nearVector(
new float[]{0.1f, 0.2f, 0.3f},
q -> q.limit(5).returnMetadata(Metadata.QUERY_PROFILE, Metadata.DISTANCE));

if (response.queryProfile() != null) {
for (var shard : response.queryProfile().shards()) {
// Per-shard execution timing breakdown for vector searches.
for (var entry : shard.searches().entrySet()) {
System.out.println(" [" + entry.getKey() + "]");
for (var detail : entry.getValue().entrySet()) {
System.out.println(" " + detail.getKey() + ": " + detail.getValue());
}
}
}
}
// END ProfileNearVector

assertThat(response.queryProfile()).isNotNull();
assertThat(response.queryProfile().shards()).isNotEmpty();
}

@Test
void testProfileBM25() {
// START ProfileBM25
CollectionHandle<Map<String, Object>> collection =
client.collections.use(COLLECTION);

var response = collection.query.bm25(
"machine learning",
q -> q.returnMetadata(Metadata.QUERY_PROFILE, Metadata.SCORE));

if (response.queryProfile() != null) {
for (var shard : response.queryProfile().shards()) {
for (var entry : shard.searches().entrySet()) {
System.out.println(" [" + entry.getKey() + "]");
for (var detail : entry.getValue().entrySet()) {
System.out.println(" " + detail.getKey() + ": " + detail.getValue());
}
}
}
}
// END ProfileBM25

assertThat(response.queryProfile()).isNotNull();
}

@Test
void testProfileHybrid() {
// START ProfileHybrid
CollectionHandle<Map<String, Object>> collection =
client.collections.use(COLLECTION);

var response = collection.query.hybrid(
"machine learning",
q -> q.limit(5).returnMetadata(Metadata.QUERY_PROFILE));

if (response.queryProfile() != null) {
for (var shard : response.queryProfile().shards()) {
for (var entry : shard.searches().entrySet()) {
System.out.println(" [" + entry.getKey() + "]");
for (var detail : entry.getValue().entrySet()) {
System.out.println(" " + detail.getKey() + ": " + detail.getValue());
}
}
}
}
// END ProfileHybrid

assertThat(response.queryProfile()).isNotNull();
}
}
Loading
Loading