chub-dev 0.1.0 → 0.2.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,984 @@
1
+ ---
2
+ name: sdk
3
+ description: "Vector database for AI applications with semantic search, hybrid search, reranking, and integrated embeddings"
4
+ metadata:
5
+ languages: "javascript"
6
+ versions: "6.1.2"
7
+ updated-on: "2025-10-26"
8
+ source: maintainer
9
+ tags: "pinecone,sdk,vector-db,ai,search"
10
+ ---
11
+ # Pinecone JavaScript/TypeScript SDK Coding Guidelines
12
+
13
+ You are a Pinecone vector database coding expert. Help me with writing code using the Pinecone SDK for JavaScript/TypeScript.
14
+
15
+ You can find the official SDK documentation and code samples here:
16
+ https://docs.pinecone.io/
17
+
18
+ ## Golden Rule: Use the Correct and Current SDK
19
+
20
+ Always use the official Pinecone TypeScript SDK for all Pinecone vector database interactions. Do not use legacy libraries or unofficial packages.
21
+
22
+ - **Library Name:** Pinecone TypeScript SDK
23
+ - **NPM Package:** `@pinecone-database/pinecone`
24
+ - **Legacy Libraries**: `pinecone-client` and other unofficial packages are not recommended
25
+
26
+ **Installation:**
27
+
28
+ - **Correct:** `npm install @pinecone-database/pinecone`
29
+
30
+ **APIs and Usage:**
31
+
32
+ - **Correct:** `import { Pinecone } from '@pinecone-database/pinecone'`
33
+ - **Correct:** `const pc = new Pinecone({})`
34
+ - **Correct:** `await pc.createIndex(...)`
35
+ - **Correct:** `pc.index('index-name')`
36
+ - **Incorrect:** `PineconeClient`
37
+ - **Incorrect:** Legacy initialization patterns
38
+
39
+ **Important Security Note:**
40
+
41
+ The Pinecone TypeScript SDK is intended for server-side use only. Using the SDK within a browser context can expose your API key(s). Always use server-side code or proxy requests through a backend.
42
+
43
+ ## Installation
44
+
45
+ Install the Pinecone SDK using npm:
46
+
47
+ ```bash
48
+ npm install @pinecone-database/pinecone
49
+ ```
50
+
51
+ **Requirements:**
52
+ - TypeScript >=4.1
53
+ - Node.js >=18.x
54
+
55
+ ## Initialization and API Key
56
+
57
+ The SDK requires creating a `Pinecone` instance for all API calls.
58
+
59
+ ### Using Environment Variables
60
+
61
+ Set your API key as an environment variable:
62
+
63
+ ```bash
64
+ export PINECONE_API_KEY="your_api_key_here"
65
+ ```
66
+
67
+ Then initialize without arguments:
68
+
69
+ ```typescript
70
+ import { Pinecone } from '@pinecone-database/pinecone';
71
+
72
+ const pc = new Pinecone();
73
+ ```
74
+
75
+ ### Using Configuration Object
76
+
77
+ Pass credentials directly:
78
+
79
+ ```typescript
80
+ import { Pinecone } from '@pinecone-database/pinecone';
81
+
82
+ const pc = new Pinecone({
83
+ apiKey: 'your_api_key_here',
84
+ });
85
+ ```
86
+
87
+ ### With Custom Retry Configuration
88
+
89
+ ```typescript
90
+ import { Pinecone } from '@pinecone-database/pinecone';
91
+
92
+ const pc = new Pinecone({
93
+ apiKey: process.env.PINECONE_API_KEY,
94
+ maxRetries: 5,
95
+ });
96
+ ```
97
+
98
+ The `maxRetries` parameter (defaults to 3) applies to operations like `upsert`, `update`, and `configureIndex`.
99
+
100
+ ## Creating Indexes
101
+
102
+ ### Serverless Index (Basic)
103
+
104
+ ```typescript
105
+ import { Pinecone } from '@pinecone-database/pinecone';
106
+
107
+ const pc = new Pinecone();
108
+
109
+ await pc.createIndex({
110
+ name: 'my-index',
111
+ dimension: 1536,
112
+ metric: 'cosine',
113
+ spec: {
114
+ serverless: {
115
+ cloud: 'aws',
116
+ region: 'us-west-2',
117
+ },
118
+ },
119
+ });
120
+ ```
121
+
122
+ ### Serverless Index with Wait
123
+
124
+ Use `waitUntilReady` to block until the index is operational:
125
+
126
+ ```typescript
127
+ await pc.createIndex({
128
+ name: 'serverless-index',
129
+ dimension: 1536,
130
+ metric: 'cosine',
131
+ spec: {
132
+ serverless: {
133
+ cloud: 'aws',
134
+ region: 'us-east-1',
135
+ },
136
+ },
137
+ waitUntilReady: true,
138
+ });
139
+ ```
140
+
141
+ ### Pod-Based Index
142
+
143
+ ```typescript
144
+ await pc.createIndex({
145
+ name: 'pod-index',
146
+ dimension: 1536,
147
+ metric: 'dotproduct',
148
+ spec: {
149
+ pod: {
150
+ environment: 'us-west-2',
151
+ podType: 'p1.x1',
152
+ pods: 1,
153
+ replicas: 1,
154
+ },
155
+ },
156
+ });
157
+ ```
158
+
159
+ ### Hybrid Search Index (Sparse-Dense)
160
+
161
+ For hybrid search supporting both dense and sparse vectors, use `dotproduct` metric:
162
+
163
+ ```typescript
164
+ await pc.createIndex({
165
+ name: 'hybrid-index',
166
+ dimension: 1024,
167
+ metric: 'dotproduct',
168
+ spec: {
169
+ serverless: {
170
+ cloud: 'aws',
171
+ region: 'us-east-1',
172
+ },
173
+ },
174
+ });
175
+ ```
176
+
177
+ **Note:** The `dotproduct` metric is the only metric that supports sparse-dense hybrid search.
178
+
179
+ ## Index Management
180
+
181
+ ### Describe Index
182
+
183
+ Get index details including status, dimension, and host:
184
+
185
+ ```typescript
186
+ const indexStats = await pc.describeIndex('my-index');
187
+ console.log(indexStats);
188
+ ```
189
+
190
+ ### List All Indexes
191
+
192
+ ```typescript
193
+ const indexList = await pc.listIndexes();
194
+ console.log(indexList.indexes);
195
+ ```
196
+
197
+ ### Delete Index
198
+
199
+ ```typescript
200
+ await pc.deleteIndex('my-index');
201
+ ```
202
+
203
+ ### Configure Index (Scale)
204
+
205
+ For pod-based indexes, adjust replicas and pod type:
206
+
207
+ ```typescript
208
+ await pc.configureIndex('pod-index', {
209
+ spec: {
210
+ pod: {
211
+ replicas: 2,
212
+ podType: 'p1.x2',
213
+ },
214
+ },
215
+ });
216
+ ```
217
+
218
+ ## Connecting to an Index
219
+
220
+ ### Basic Connection
221
+
222
+ ```typescript
223
+ import { Pinecone } from '@pinecone-database/pinecone';
224
+
225
+ const pc = new Pinecone();
226
+ const index = pc.index('my-index');
227
+ ```
228
+
229
+ ### Connection with Namespace
230
+
231
+ ```typescript
232
+ const pc = new Pinecone();
233
+ const index = pc.index('my-index').namespace('my-namespace');
234
+ ```
235
+
236
+ ### Connection with Host (Faster)
237
+
238
+ If you know the index host, connect directly:
239
+
240
+ ```typescript
241
+ const pc = new Pinecone();
242
+ const index = pc.index('my-index', 'https://my-index-abc123.svc.pinecone.io');
243
+ ```
244
+
245
+ ## Upserting Vectors
246
+
247
+ ### Dense Vectors (Basic)
248
+
249
+ ```typescript
250
+ const pc = new Pinecone();
251
+ const index = pc.index('my-index');
252
+
253
+ await index.upsert([
254
+ {
255
+ id: 'vec1',
256
+ values: [0.1, 0.2, 0.3, 0.4, 0.5],
257
+ },
258
+ {
259
+ id: 'vec2',
260
+ values: [0.2, 0.3, 0.4, 0.5, 0.6],
261
+ },
262
+ ]);
263
+ ```
264
+
265
+ ### Dense Vectors with Metadata
266
+
267
+ ```typescript
268
+ await index.upsert([
269
+ {
270
+ id: 'vec1',
271
+ values: [0.1, 0.2, 0.3, 0.4, 0.5],
272
+ metadata: {
273
+ genre: 'comedy',
274
+ year: 2020,
275
+ title: 'Movie Title',
276
+ },
277
+ },
278
+ {
279
+ id: 'vec2',
280
+ values: [0.2, 0.3, 0.4, 0.5, 0.6],
281
+ metadata: {
282
+ genre: 'action',
283
+ year: 2021,
284
+ title: 'Another Movie',
285
+ },
286
+ },
287
+ ]);
288
+ ```
289
+
290
+ ### Namespaced Upsert
291
+
292
+ ```typescript
293
+ const pc = new Pinecone();
294
+ const ns = pc.index('my-index').namespace('example-namespace');
295
+
296
+ await ns.upsert([
297
+ {
298
+ id: 'vec1',
299
+ values: [0.1, 0.2, 0.3],
300
+ metadata: { category: 'A' },
301
+ },
302
+ ]);
303
+ ```
304
+
305
+ ### Batch Upsert (Large Datasets)
306
+
307
+ For upserting many vectors, batch them in groups of up to 1,000 records (max 2 MB per batch):
308
+
309
+ ```typescript
310
+ const batchSize = 1000;
311
+ const vectors = []; // Your vector array
312
+
313
+ for (let i = 0; i < vectors.length; i += batchSize) {
314
+ const batch = vectors.slice(i, i + batchSize);
315
+ await index.upsert(batch);
316
+ }
317
+ ```
318
+
319
+ ### Sparse-Dense Vectors (Hybrid Search)
320
+
321
+ ```typescript
322
+ await index.upsert([
323
+ {
324
+ id: 'vec1',
325
+ values: [0.1, 0.2, 0.3], // Dense vector
326
+ sparseValues: {
327
+ indices: [10, 45, 16],
328
+ values: [0.5, 0.5, 0.2],
329
+ },
330
+ metadata: { text: 'original text content' },
331
+ },
332
+ ]);
333
+ ```
334
+
335
+ ## Querying Vectors
336
+
337
+ ### Basic Query (Dense)
338
+
339
+ ```typescript
340
+ const pc = new Pinecone();
341
+ const index = pc.index('my-index');
342
+
343
+ const queryResponse = await index.query({
344
+ vector: [0.1, 0.2, 0.3, 0.4, 0.5],
345
+ topK: 10,
346
+ includeMetadata: true,
347
+ includeValues: false,
348
+ });
349
+
350
+ console.log(queryResponse.matches);
351
+ ```
352
+
353
+ ### Query with Metadata Filter
354
+
355
+ ```typescript
356
+ const queryResponse = await index.query({
357
+ vector: [0.1, 0.2, 0.3, 0.4, 0.5],
358
+ topK: 5,
359
+ filter: {
360
+ genre: { $eq: 'comedy' },
361
+ },
362
+ includeMetadata: true,
363
+ });
364
+ ```
365
+
366
+ ### Complex Metadata Filters
367
+
368
+ ```typescript
369
+ // Multiple conditions with $and
370
+ const response = await index.query({
371
+ vector: [0.1, 0.2, 0.3],
372
+ topK: 10,
373
+ filter: {
374
+ $and: [
375
+ { genre: { $eq: 'comedy' } },
376
+ { year: { $gte: 2020 } },
377
+ ],
378
+ },
379
+ includeMetadata: true,
380
+ });
381
+
382
+ // Using $or operator
383
+ const response2 = await index.query({
384
+ vector: [0.1, 0.2, 0.3],
385
+ topK: 10,
386
+ filter: {
387
+ $or: [
388
+ { genre: { $eq: 'comedy' } },
389
+ { genre: { $eq: 'drama' } },
390
+ ],
391
+ },
392
+ includeMetadata: true,
393
+ });
394
+
395
+ // Using $in for multiple values
396
+ const response3 = await index.query({
397
+ vector: [0.1, 0.2, 0.3],
398
+ topK: 10,
399
+ filter: {
400
+ genre: { $in: ['comedy', 'action', 'drama'] },
401
+ },
402
+ includeMetadata: true,
403
+ });
404
+ ```
405
+
406
+ ### Query by ID
407
+
408
+ ```typescript
409
+ const queryResponse = await index.query({
410
+ id: 'vec1',
411
+ topK: 10,
412
+ includeMetadata: true,
413
+ });
414
+ ```
415
+
416
+ ### Namespaced Query
417
+
418
+ ```typescript
419
+ const ns = pc.index('my-index').namespace('example-namespace');
420
+
421
+ const queryResponse = await ns.query({
422
+ vector: [0.1, 0.2, 0.3],
423
+ topK: 5,
424
+ includeMetadata: true,
425
+ });
426
+ ```
427
+
428
+ ### Hybrid Query (Sparse-Dense)
429
+
430
+ ```typescript
431
+ const queryResponse = await index.query({
432
+ vector: [0.1, 0.2, 0.3], // Dense query vector
433
+ sparseVector: {
434
+ indices: [10, 45, 16],
435
+ values: [0.5, 0.5, 0.2],
436
+ },
437
+ topK: 10,
438
+ includeMetadata: true,
439
+ });
440
+ ```
441
+
442
+ ## Fetching Vectors
443
+
444
+ ### Fetch by IDs
445
+
446
+ ```typescript
447
+ const pc = new Pinecone();
448
+ const index = pc.index('my-index');
449
+
450
+ const fetchResponse = await index.fetch(['vec1', 'vec2', 'vec3']);
451
+ console.log(fetchResponse.records);
452
+ ```
453
+
454
+ ### Fetch from Namespace
455
+
456
+ ```typescript
457
+ const ns = pc.index('my-index').namespace('example-namespace');
458
+ const fetchResponse = await ns.fetch(['vec1', 'vec2']);
459
+ console.log(fetchResponse.records);
460
+ ```
461
+
462
+ ## Updating Vectors
463
+
464
+ ### Update Values
465
+
466
+ ```typescript
467
+ const pc = new Pinecone();
468
+ const index = pc.index('my-index');
469
+
470
+ await index.update({
471
+ id: 'vec1',
472
+ values: [0.9, 0.8, 0.7, 0.6, 0.5],
473
+ });
474
+ ```
475
+
476
+ ### Update Metadata
477
+
478
+ ```typescript
479
+ await index.update({
480
+ id: 'vec1',
481
+ metadata: {
482
+ genre: 'documentary',
483
+ year: 2023,
484
+ },
485
+ });
486
+ ```
487
+
488
+ ### Update with Namespace
489
+
490
+ ```typescript
491
+ const ns = pc.index('my-index').namespace('example-namespace');
492
+
493
+ await ns.update({
494
+ id: 'vec1',
495
+ values: [0.1, 0.2, 0.3],
496
+ metadata: { updated: true },
497
+ });
498
+ ```
499
+
500
+ ## Deleting Vectors
501
+
502
+ ### Delete by IDs
503
+
504
+ ```typescript
505
+ const pc = new Pinecone();
506
+ const index = pc.index('my-index');
507
+
508
+ await index.deleteOne('vec1');
509
+
510
+ // Delete multiple
511
+ await index.deleteMany(['vec1', 'vec2', 'vec3']);
512
+ ```
513
+
514
+ ### Delete with Metadata Filter
515
+
516
+ ```typescript
517
+ await index.deleteMany({
518
+ filter: {
519
+ genre: { $eq: 'comedy' },
520
+ },
521
+ });
522
+ ```
523
+
524
+ ### Delete All in Namespace
525
+
526
+ ```typescript
527
+ const ns = pc.index('my-index').namespace('example-namespace');
528
+ await ns.deleteAll();
529
+ ```
530
+
531
+ **Warning:** Deleting all records from a namespace will also delete the namespace itself. This operation is irreversible.
532
+
533
+ ### Delete from Specific Namespace
534
+
535
+ ```typescript
536
+ const index = pc.index('my-index');
537
+
538
+ await index.namespace('example-namespace').deleteMany(['vec1', 'vec2']);
539
+ ```
540
+
541
+ ## Index Statistics
542
+
543
+ ### Get Index Stats
544
+
545
+ ```typescript
546
+ const pc = new Pinecone();
547
+ const index = pc.index('my-index');
548
+
549
+ const stats = await index.describeIndexStats();
550
+ console.log(stats);
551
+ ```
552
+
553
+ Returns information including:
554
+ - Total vector count
555
+ - Dimension
556
+ - Index fullness
557
+ - Namespaces with vector counts
558
+
559
+ ### Get Stats with Filter
560
+
561
+ ```typescript
562
+ const stats = await index.describeIndexStats({
563
+ filter: {
564
+ genre: { $eq: 'comedy' },
565
+ },
566
+ });
567
+ ```
568
+
569
+ ## Integrated Inference (Embeddings)
570
+
571
+ Pinecone provides hosted embedding models through the Inference API.
572
+
573
+ ### Generate Embeddings
574
+
575
+ ```typescript
576
+ import { Pinecone } from '@pinecone-database/pinecone';
577
+
578
+ const pc = new Pinecone();
579
+
580
+ // Embed documents
581
+ const embeddings = await pc.inference.embed({
582
+ model: 'multilingual-e5-large',
583
+ inputs: [
584
+ { text: 'Turkey is a classic meat to eat at American Thanksgiving.' },
585
+ { text: 'Many people enjoy the beautiful mosques in Turkey.' },
586
+ ],
587
+ parameters: {
588
+ inputType: 'passage',
589
+ truncate: 'END',
590
+ },
591
+ });
592
+
593
+ console.log(embeddings);
594
+ ```
595
+
596
+ ### Embed Queries
597
+
598
+ ```typescript
599
+ const pc = new Pinecone();
600
+
601
+ const queryEmbedding = await pc.inference.embed({
602
+ model: 'multilingual-e5-large',
603
+ inputs: [{ text: 'How should I prepare my turkey?' }],
604
+ parameters: {
605
+ inputType: 'query',
606
+ truncate: 'END',
607
+ },
608
+ });
609
+
610
+ // Use the embedding for querying
611
+ const index = pc.index('my-index');
612
+ const results = await index.query({
613
+ vector: queryEmbedding[0].values,
614
+ topK: 10,
615
+ includeMetadata: true,
616
+ });
617
+ ```
618
+
619
+ ### Available Embedding Models
620
+
621
+ - `multilingual-e5-large`: Efficient dense embedding model trained on multilingual datasets
622
+ - `pinecone-sparse-english-v0`: Sparse embedding model for keyword or hybrid semantic/keyword search
623
+
624
+ ## Integrated Records (Auto-Embedding)
625
+
626
+ For indexes with integrated embedding, use `upsertRecords` to automatically convert text to vectors.
627
+
628
+ ### Upsert with Auto-Embedding
629
+
630
+ ```typescript
631
+ const pc = new Pinecone();
632
+ const index = pc.index('integrated-index').namespace('my-namespace');
633
+
634
+ await index.upsertRecords([
635
+ {
636
+ id: 'rec1',
637
+ chunk_text: "Apple's first product was the Apple I computer.",
638
+ metadata: { category: 'tech' },
639
+ },
640
+ {
641
+ id: 'rec2',
642
+ chunk_text: 'The company was founded in 1976.',
643
+ metadata: { category: 'history' },
644
+ },
645
+ ]);
646
+ ```
647
+
648
+ ### Query with Integrated Embedding
649
+
650
+ ```typescript
651
+ const results = await index.queryRecords({
652
+ query: 'Tell me about Apple computers',
653
+ topK: 5,
654
+ filter: { category: { $eq: 'tech' } },
655
+ includeMetadata: true,
656
+ });
657
+
658
+ console.log(results.matches);
659
+ ```
660
+
661
+ ## Namespaces
662
+
663
+ Namespaces partition records within an index and enable multitenancy.
664
+
665
+ ### Create Namespace (Implicit)
666
+
667
+ Namespaces are created automatically when you upsert to them:
668
+
669
+ ```typescript
670
+ const ns1 = pc.index('my-index').namespace('customer-1');
671
+ await ns1.upsert([{ id: 'vec1', values: [0.1, 0.2, 0.3] }]);
672
+
673
+ const ns2 = pc.index('my-index').namespace('customer-2');
674
+ await ns2.upsert([{ id: 'vec1', values: [0.4, 0.5, 0.6] }]);
675
+ ```
676
+
677
+ ### List Namespaces
678
+
679
+ ```typescript
680
+ const stats = await index.describeIndexStats();
681
+ console.log(Object.keys(stats.namespaces));
682
+ ```
683
+
684
+ ### Default Namespace
685
+
686
+ If no namespace is specified, vectors are stored in the `"__default__"` namespace:
687
+
688
+ ```typescript
689
+ const index = pc.index('my-index');
690
+ // This uses the default namespace
691
+ await index.upsert([{ id: 'vec1', values: [0.1, 0.2, 0.3] }]);
692
+ ```
693
+
694
+ ## Reranking
695
+
696
+ Use Pinecone's reranking models to reorder results by relevance.
697
+
698
+ ### Rerank Results
699
+
700
+ ```typescript
701
+ import { Pinecone } from '@pinecone-database/pinecone';
702
+
703
+ const pc = new Pinecone();
704
+
705
+ const reranked = await pc.inference.rerank({
706
+ model: 'bge-reranker-v2-m3',
707
+ query: 'What is the capital of France?',
708
+ documents: [
709
+ { id: 'doc1', text: 'Paris is the capital of France.' },
710
+ { id: 'doc2', text: 'London is the capital of England.' },
711
+ { id: 'doc3', text: 'Berlin is the capital of Germany.' },
712
+ ],
713
+ topN: 2,
714
+ returnDocuments: true,
715
+ });
716
+
717
+ console.log(reranked);
718
+ ```
719
+
720
+ ## Collections (Backups)
721
+
722
+ Collections are static snapshots of an index that can be used to create new indexes.
723
+
724
+ ### Create Collection
725
+
726
+ ```typescript
727
+ const pc = new Pinecone();
728
+
729
+ await pc.createCollection({
730
+ name: 'my-collection',
731
+ source: 'my-index',
732
+ });
733
+ ```
734
+
735
+ ### List Collections
736
+
737
+ ```typescript
738
+ const collections = await pc.listCollections();
739
+ console.log(collections);
740
+ ```
741
+
742
+ ### Create Index from Collection
743
+
744
+ ```typescript
745
+ await pc.createIndex({
746
+ name: 'new-index-from-backup',
747
+ dimension: 1536,
748
+ metric: 'cosine',
749
+ spec: {
750
+ serverless: {
751
+ cloud: 'aws',
752
+ region: 'us-west-2',
753
+ },
754
+ },
755
+ sourceCollection: 'my-collection',
756
+ });
757
+ ```
758
+
759
+ ### Delete Collection
760
+
761
+ ```typescript
762
+ await pc.deleteCollection('my-collection');
763
+ ```
764
+
765
+ ## Error Handling
766
+
767
+ ### Basic Error Handling
768
+
769
+ ```typescript
770
+ import { Pinecone, PineconeConnectionError } from '@pinecone-database/pinecone';
771
+
772
+ const pc = new Pinecone();
773
+ const index = pc.index('my-index');
774
+
775
+ try {
776
+ await index.query({
777
+ vector: [0.1, 0.2, 0.3],
778
+ topK: 10,
779
+ });
780
+ } catch (error) {
781
+ if (error instanceof PineconeConnectionError) {
782
+ console.error('Connection error:', error.message);
783
+ } else {
784
+ console.error('Unexpected error:', error);
785
+ }
786
+ }
787
+ ```
788
+
789
+ ### Retry Configuration
790
+
791
+ ```typescript
792
+ const pc = new Pinecone({
793
+ apiKey: process.env.PINECONE_API_KEY,
794
+ maxRetries: 5, // Increase retries for operations
795
+ });
796
+ ```
797
+
798
+ ## Performance Best Practices
799
+
800
+ ### Batch Operations
801
+
802
+ Always batch upsert operations for better throughput:
803
+
804
+ ```typescript
805
+ // Good: Batch upsert
806
+ const vectors = generateVectors(1000);
807
+ await index.upsert(vectors);
808
+
809
+ // Bad: Individual upserts
810
+ for (const vector of vectors) {
811
+ await index.upsert([vector]); // Don't do this
812
+ }
813
+ ```
814
+
815
+ ### Parallel Requests
816
+
817
+ Use Promise.all for independent parallel operations:
818
+
819
+ ```typescript
820
+ const [stats, listResult, queryResult] = await Promise.all([
821
+ index.describeIndexStats(),
822
+ pc.listIndexes(),
823
+ index.query({ vector: [0.1, 0.2, 0.3], topK: 5 }),
824
+ ]);
825
+ ```
826
+
827
+ ### Connection Reuse
828
+
829
+ Reuse the index connection instead of recreating it:
830
+
831
+ ```typescript
832
+ // Good: Create once, reuse
833
+ const index = pc.index('my-index');
834
+ for (let i = 0; i < 100; i++) {
835
+ await index.query({ vector: getVector(i), topK: 5 });
836
+ }
837
+
838
+ // Bad: Recreate each time
839
+ for (let i = 0; i < 100; i++) {
840
+ const index = pc.index('my-index'); // Don't do this
841
+ await index.query({ vector: getVector(i), topK: 5 });
842
+ }
843
+ ```
844
+
845
+ ## Metadata Filtering Operators
846
+
847
+ Pinecone supports MongoDB-style query operators for metadata filtering:
848
+
849
+ - `$eq`: Equal to
850
+ - `$ne`: Not equal to
851
+ - `$gt`: Greater than
852
+ - `$gte`: Greater than or equal to
853
+ - `$lt`: Less than
854
+ - `$lte`: Less than or equal to
855
+ - `$in`: In array
856
+ - `$nin`: Not in array
857
+ - `$exists`: Field exists
858
+ - `$and`: Logical AND
859
+ - `$or`: Logical OR
860
+
861
+ ### Example: Complex Filter
862
+
863
+ ```typescript
864
+ const results = await index.query({
865
+ vector: [0.1, 0.2, 0.3],
866
+ topK: 10,
867
+ filter: {
868
+ $and: [
869
+ { year: { $gte: 2020, $lte: 2023 } },
870
+ {
871
+ $or: [
872
+ { genre: { $eq: 'comedy' } },
873
+ { genre: { $eq: 'drama' } },
874
+ ],
875
+ },
876
+ { rating: { $exists: true } },
877
+ ],
878
+ },
879
+ includeMetadata: true,
880
+ });
881
+ ```
882
+
883
+ ## Limits and Constraints
884
+
885
+ - **Max vectors per upsert**: 1,000 records (or 2 MB per batch)
886
+ - **Max vectors per upsert (with text)**: 96 records
887
+ - **Metadata size per vector**: 40 KB max
888
+ - **Record ID length**: 512 characters max
889
+ - **Dense vector dimensions**: Up to 20,000
890
+ - **Sparse vector non-zero values**: 2,048 max
891
+ - **Top-K query limit**: 10,000
892
+
893
+ ## Common Patterns
894
+
895
+ ### Pattern: Upsert and Query Flow
896
+
897
+ ```typescript
898
+ import { Pinecone } from '@pinecone-database/pinecone';
899
+
900
+ const pc = new Pinecone();
901
+
902
+ // Create index
903
+ await pc.createIndex({
904
+ name: 'example-index',
905
+ dimension: 1536,
906
+ metric: 'cosine',
907
+ spec: {
908
+ serverless: { cloud: 'aws', region: 'us-west-2' },
909
+ },
910
+ waitUntilReady: true,
911
+ });
912
+
913
+ // Connect and upsert
914
+ const index = pc.index('example-index');
915
+ await index.upsert([
916
+ {
917
+ id: 'doc1',
918
+ values: [0.1, 0.2, 0.3], // ... 1536 dimensions
919
+ metadata: { title: 'Document 1', category: 'A' },
920
+ },
921
+ ]);
922
+
923
+ // Query
924
+ const results = await index.query({
925
+ vector: [0.1, 0.2, 0.3], // ... 1536 dimensions
926
+ topK: 5,
927
+ includeMetadata: true,
928
+ });
929
+
930
+ console.log(results.matches);
931
+ ```
932
+
933
+ ### Pattern: Multi-Tenant with Namespaces
934
+
935
+ ```typescript
936
+ const pc = new Pinecone();
937
+ const index = pc.index('multi-tenant-index');
938
+
939
+ // Tenant 1
940
+ const tenant1 = index.namespace('tenant-1');
941
+ await tenant1.upsert([
942
+ { id: 'vec1', values: [0.1, 0.2, 0.3], metadata: { user: 'user1' } },
943
+ ]);
944
+
945
+ // Tenant 2
946
+ const tenant2 = index.namespace('tenant-2');
947
+ await tenant2.upsert([
948
+ { id: 'vec1', values: [0.4, 0.5, 0.6], metadata: { user: 'user2' } },
949
+ ]);
950
+
951
+ // Query tenant-specific data
952
+ const tenant1Results = await tenant1.query({
953
+ vector: [0.1, 0.2, 0.3],
954
+ topK: 5,
955
+ });
956
+ ```
957
+
958
+ ### Pattern: Hybrid Search with Weighting
959
+
960
+ ```typescript
961
+ // Alpha controls dense vs sparse weighting
962
+ // alpha=1 is pure dense, alpha=0 is pure sparse
963
+ const alpha = 0.7;
964
+
965
+ const denseVector = [0.1, 0.2, 0.3];
966
+ const sparseVector = {
967
+ indices: [10, 45, 16],
968
+ values: [0.5, 0.5, 0.2],
969
+ };
970
+
971
+ // Apply weighting
972
+ const weightedDense = denseVector.map(v => v * alpha);
973
+ const weightedSparse = {
974
+ indices: sparseVector.indices,
975
+ values: sparseVector.values.map(v => v * (1 - alpha)),
976
+ };
977
+
978
+ const results = await index.query({
979
+ vector: weightedDense,
980
+ sparseVector: weightedSparse,
981
+ topK: 10,
982
+ includeMetadata: true,
983
+ });
984
+ ```