Skip to content

Commit

Permalink
Add more integration tests for query
Browse files Browse the repository at this point in the history
  • Loading branch information
jhamon committed Sep 27, 2023
1 parent e736a43 commit ba9deb7
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 30 deletions.
2 changes: 1 addition & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ module.exports = {
testPathIgnorePatterns: ['src/integration'],
testTimeout: 100000,
verbose: true,
detectOpenHandles: true,
detectOpenHandles: false,
collectCoverageFrom: [
'<rootDir>/src/**/*.ts',
'!**/src/pinecone-generated-ts-fetch/**',
Expand Down
13 changes: 7 additions & 6 deletions src/integration/data/deleteMany.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
import { Pinecone, Index } from '../../index';
import {
randomString,
createIndexIfDoesNotExist,
generateRecords,
} from '../test-helpers';
import { randomString, generateRecords } from '../test-helpers';

describe('deleteMany', () => {
const INDEX_NAME = 'ts-integration';
Expand All @@ -12,7 +8,12 @@ describe('deleteMany', () => {
beforeAll(async () => {
pinecone = new Pinecone();

await createIndexIfDoesNotExist(pinecone, INDEX_NAME);
await pinecone.createIndex({
name: INDEX_NAME,
dimension: 5,
waitUntilReady: true,
suppressConflicts: true,
});

namespace = randomString(16);
index = pinecone.index(INDEX_NAME);
Expand Down
103 changes: 103 additions & 0 deletions src/integration/data/query.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import { Pinecone, Index } from '../../index';
import { randomString, generateRecords } from '../test-helpers';

describe('query', () => {
const INDEX_NAME = 'ts-integration';
let pinecone: Pinecone, index: Index, ns: Index, namespace: string;

beforeAll(async () => {
pinecone = new Pinecone();

await pinecone.createIndex({
name: INDEX_NAME,
dimension: 5,
waitUntilReady: true,
suppressConflicts: true,
});

namespace = randomString(16);
index = pinecone.index(INDEX_NAME);
ns = index.namespace(namespace);
});

afterEach(async () => {
await ns.deleteAll();
});

test('query by id', async () => {
const recordsToUpsert = generateRecords(5, 3);
expect(recordsToUpsert).toHaveLength(3);
expect(recordsToUpsert[0].id).toEqual('0');
expect(recordsToUpsert[1].id).toEqual('1');
expect(recordsToUpsert[2].id).toEqual('2');

await ns.upsert(recordsToUpsert);

// Check records got upserted
const stats = await ns.describeIndexStats();
if (stats.namespaces) {
expect(stats.namespaces[namespace].recordCount).toEqual(3);
} else {
fail('Expected namespaces to be defined');
}

const topK = 2;
const results = await ns.query({ id: '0', topK });
expect(results.matches).toBeDefined();

expect(results.matches?.length).toEqual(topK);
});

test('query when topK is greater than number of records', async () => {
const numberOfRecords = 3;
const recordsToUpsert = generateRecords(5, numberOfRecords);
expect(recordsToUpsert).toHaveLength(3);
expect(recordsToUpsert[0].id).toEqual('0');
expect(recordsToUpsert[1].id).toEqual('1');
expect(recordsToUpsert[2].id).toEqual('2');

await ns.upsert(recordsToUpsert);

const topK = 5;
const results = await ns.query({ id: '0', topK });
expect(results.matches).toBeDefined();

expect(results.matches?.length).toEqual(numberOfRecords);
});

test('with invalid id, returns empty results', async () => {
const recordsToUpsert = generateRecords(5, 3);
expect(recordsToUpsert).toHaveLength(3);
expect(recordsToUpsert[0].id).toEqual('0');
expect(recordsToUpsert[1].id).toEqual('1');
expect(recordsToUpsert[2].id).toEqual('2');

await ns.upsert(recordsToUpsert);

const topK = 2;
const results = await ns.query({ id: '100', topK });
expect(results.matches).toBeDefined();

expect(results.matches?.length).toEqual(0);
});

test('query with vector values', async () => {
const numberOfRecords = 3;
const recordsToUpsert = generateRecords(5, numberOfRecords);
expect(recordsToUpsert).toHaveLength(3);
expect(recordsToUpsert[0].id).toEqual('0');
expect(recordsToUpsert[1].id).toEqual('1');
expect(recordsToUpsert[2].id).toEqual('2');

await ns.upsert(recordsToUpsert);

const topK = 1;
const results = await ns.query({
vector: [0.11, 0.22, 0.33, 0.44, 0.55],
topK,
});
expect(results.matches).toBeDefined();

expect(results.matches?.length).toEqual(topK);
});
});
21 changes: 0 additions & 21 deletions src/integration/test-helpers.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { Pinecone } from '../index';
import type { PineconeRecord, RecordSparseValues } from '../index';

export const randomString = (length) => {
Expand All @@ -14,26 +13,6 @@ export const randomString = (length) => {
return result;
};

export const createIndexIfDoesNotExist = async (
pinecone: Pinecone,
indexName: string
) => {
const indexList = await pinecone.listIndexes();
let found = false;
indexList.forEach((i) => {
if (i.name === indexName) {
found = true;
}
});
if (!found) {
await pinecone.createIndex({
name: indexName,
dimension: 5,
waitUntilReady: true,
});
}
};

export const generateRecords = (
dimension: number,
quantity: number,
Expand Down
4 changes: 2 additions & 2 deletions src/utils/fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ export const getFetch = (config: PineconeConfiguration) => {
if (config.fetchApi) {
// User-provided fetch implementation, if any, takes precedence.
return config.fetchApi;
} else if (fetch) {
} else if (global.fetch) {
// If a fetch implementation is already present in the global
// scope, use that. This should prevent confusing failures in
// nextjs projects where @vercel/fetch is mandated and
// other implementations are stubbed out.
return fetch;
return global.fetch;
} else {
// Use polyfill as last resort
return crossFetch;
Expand Down

0 comments on commit ba9deb7

Please sign in to comment.