Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
80 changes: 80 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -697,6 +697,86 @@ List<Float> values = Arrays.asList(1F, 2F, 3F);
UpdateResponse updateResponse = index.update("v1", values, "example-namespace");
```

## Fetch vectors by metadata

The following example fetches vectors by metadata filter.

```java
import io.pinecone.clients.Index;
import io.pinecone.clients.Pinecone;
import io.pinecone.proto.FetchByMetadataResponse;
import com.google.protobuf.Struct;
import com.google.protobuf.Value;
...

Pinecone pinecone = new Pinecone.Builder("PINECONE_API_KEY").build();
Index index = pinecone.getIndexConnection("example-index");

// Create a metadata filter
Struct filter = Struct.newBuilder()
.putFields("genre", Value.newBuilder()
.setStructValue(Struct.newBuilder()
.putFields("$eq", Value.newBuilder()
.setStringValue("action")
.build()))
.build())
.build();

// Fetch vectors by metadata with limit
FetchByMetadataResponse response = index.fetchByMetadata("example-namespace", filter, 10, null);

// Fetch with pagination
String paginationToken = null;
FetchByMetadataResponse fetchResponse = index.fetchByMetadata("example-namespace", filter, 100, paginationToken);

// Continue pagination if needed
if (fetchResponse.hasPagination() &&
fetchResponse.getPagination().getNext() != null &&
!fetchResponse.getPagination().getNext().isEmpty()) {
FetchByMetadataResponse nextPage = index.fetchByMetadata(
"example-namespace", filter, 100, fetchResponse.getPagination().getNext());
}
```

## Update vectors by metadata

The following example updates vectors by metadata filter.

```java
import io.pinecone.clients.Index;
import io.pinecone.clients.Pinecone;
import io.pinecone.proto.UpdateResponse;
import com.google.protobuf.Struct;
import com.google.protobuf.Value;
...

Pinecone pinecone = new Pinecone.Builder("PINECONE_API_KEY").build();
Index index = pinecone.getIndexConnection("example-index");

// Create a filter to match vectors
Struct filter = Struct.newBuilder()
.putFields("genre", Value.newBuilder()
.setStructValue(Struct.newBuilder()
.putFields("$eq", Value.newBuilder()
.setStringValue("action")
.build()))
.build())
.build();

// Create new metadata to apply
Struct newMetadata = Struct.newBuilder()
.putFields("updated", Value.newBuilder().setStringValue("true").build())
.putFields("year", Value.newBuilder().setStringValue("2024").build())
.build();

// Dry run to check how many records would be updated
UpdateResponse dryRunResponse = index.updateByMetadata(filter, newMetadata, "example-namespace", true);
int matchedRecords = dryRunResponse.getMatchedRecords();

// Actually perform the update
UpdateResponse updateResponse = index.updateByMetadata(filter, newMetadata, "example-namespace", false);
```

## Create namespace

The following example shows how to create a namespace.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
package io.pinecone.integration.dataPlane;

import com.google.protobuf.Struct;
import com.google.protobuf.Value;
import io.pinecone.clients.AsyncIndex;
import io.pinecone.clients.Index;
import io.pinecone.helpers.RandomStringBuilder;
import io.pinecone.helpers.TestResourcesManager;
import io.pinecone.proto.FetchByMetadataResponse;
import io.pinecone.proto.UpdateResponse;
import io.pinecone.unsigned_indices_model.VectorWithUnsignedIndices;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ExecutionException;

import static io.pinecone.helpers.AssertRetry.assertWithRetry;
import static io.pinecone.helpers.BuildUpsertRequest.*;
import static org.junit.jupiter.api.Assertions.*;

public class FetchAndUpdateByMetadataTest {

private static final TestResourcesManager indexManager = TestResourcesManager.getInstance();
private static Index index;
private static AsyncIndex asyncIndex;
private static final String namespace = RandomStringBuilder.build("ns", 8);

@BeforeAll
public static void setUp() throws InterruptedException {
int dimension = indexManager.getDimension();
index = indexManager.getOrCreateServerlessIndexConnection();
asyncIndex = indexManager.getOrCreateServerlessAsyncIndexConnection();

// Upsert vectors with metadata for testing
int numOfVectors = 5;
List<String> upsertIds = getIdsList(numOfVectors);
List<VectorWithUnsignedIndices> vectorsToUpsert = new ArrayList<>(numOfVectors);

// Upsert vectors with different metadata values
for (int i = 0; i < numOfVectors; i++) {
Struct metadata = generateMetadataStruct(i % 3, (i + 1) % 3);
VectorWithUnsignedIndices vector = new VectorWithUnsignedIndices(
upsertIds.get(i),
generateVectorValuesByDimension(dimension),
metadata,
null
);
vectorsToUpsert.add(vector);
}

index.upsert(vectorsToUpsert, namespace);

// Wait for vectors to be indexed
Thread.sleep(5000);
}

@AfterAll
public static void cleanUp() {
index.close();
asyncIndex.close();
}

@Test
public void fetchByMetadataSyncTest() throws InterruptedException {
HashMap<String, List<String>> metadataMap = createAndGetMetadataMap();
String filterValue = metadataMap.get(metadataFields[0]).get(0);

Struct filter = Struct.newBuilder()
.putFields(metadataFields[0], Value.newBuilder()
.setStructValue(Struct.newBuilder()
.putFields("$eq", Value.newBuilder()
.setStringValue(filterValue)
.build()))
.build())
.build();

assertWithRetry(() -> {
FetchByMetadataResponse response = index.fetchByMetadata(namespace, filter, 10, null);
assertNotNull(response);
assertTrue(response.getVectorsCount() > 0);
}, 3);
}

@Test
public void updateByMetadataSyncTest() throws InterruptedException {
HashMap<String, List<String>> metadataMap = createAndGetMetadataMap();
String filterValue = metadataMap.get(metadataFields[0]).get(0);

Struct filter = Struct.newBuilder()
.putFields(metadataFields[0], Value.newBuilder()
.setStructValue(Struct.newBuilder()
.putFields("$eq", Value.newBuilder()
.setStringValue(filterValue)
.build()))
.build())
.build();

Struct newMetadata = Struct.newBuilder()
.putFields("updated", Value.newBuilder().setStringValue("true").build())
.build();

assertWithRetry(() -> {
UpdateResponse response = index.updateByMetadata(filter, newMetadata, namespace, false);
assertNotNull(response);
assertTrue(response.getMatchedRecords() > 0);
}, 3);
}

@Test
public void fetchByMetadataAsyncTest() throws InterruptedException, ExecutionException {
HashMap<String, List<String>> metadataMap = createAndGetMetadataMap();
String filterValue = metadataMap.get(metadataFields[1]).get(0);

Struct filter = Struct.newBuilder()
.putFields(metadataFields[1], Value.newBuilder()
.setStructValue(Struct.newBuilder()
.putFields("$eq", Value.newBuilder()
.setStringValue(filterValue)
.build()))
.build())
.build();

assertWithRetry(() -> {
FetchByMetadataResponse response = asyncIndex.fetchByMetadata(namespace, filter, 10, null).get();
assertNotNull(response);
assertTrue(response.getVectorsCount() > 0);
}, 3);
}

@Test
public void updateByMetadataAsyncTest() throws InterruptedException, ExecutionException {
HashMap<String, List<String>> metadataMap = createAndGetMetadataMap();
String filterValue = metadataMap.get(metadataFields[1]).get(0);

Struct filter = Struct.newBuilder()
.putFields(metadataFields[1], Value.newBuilder()
.setStructValue(Struct.newBuilder()
.putFields("$eq", Value.newBuilder()
.setStringValue(filterValue)
.build()))
.build())
.build();

Struct newMetadata = Struct.newBuilder()
.putFields("async_updated", Value.newBuilder().setStringValue("true").build())
.build();

assertWithRetry(() -> {
UpdateResponse response = asyncIndex.updateByMetadata(filter, newMetadata, namespace, false).get();
assertNotNull(response);
assertTrue(response.getMatchedRecords() > 0);
}, 3);
}
}
Loading
Loading