adachsoft / vector-store-json-file
JSON file based implementation of vector store contracts
Package info
gitlab.com/a.adach/vector-store-json-file
pkg:composer/adachsoft/vector-store-json-file
Requires
- php: ^8.3
- adachsoft/collection: ^3.0
- adachsoft/vector-store-contracts: ^0.4.0
Requires (Dev)
- adachsoft/php-code-style: ^0.7
- friendsofphp/php-cs-fixer: ^3.95
- phpstan/phpstan: ^2.1
- phpunit/phpunit: ^13.1
- rector/rector: ^2.4
- symplify/phpstan-rules: ^14.9
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
Overview
adachsoft/vector-store-json-file is a file-based implementation of the VectorStoreInterface from the adachsoft/vector-store-contracts package.
Each vector collection is stored as a single JSON file on disk. The JSON file contains:
- global configuration of the collection (dimensions, distance metric),
- all vector records (embeddings),
- arbitrary metadata attached to each record.
This package is intended for small to medium vector stores where a simple JSON file is sufficient and a database or external service would be overkill.
Requirements
- PHP 8.3 or higher
- Composer
- Runtime dependencies:
adachsoft/vector-store-contracts(vector store contracts and DTOs)adachsoft/collection(immutable collections for vectors and metadata)
Installation
Install the package via Composer:
composer require adachsoft/vector-store-json-file
Usage
Basic store setup
use AdachSoft\VectorStoreJsonFile\JsonFileVectorCollectionRepositoryFactory;
use AdachSoft\VectorStoreJsonFile\JsonFileVectorStore;
use AdachSoft\VectorStoreContracts\Enum\DistanceMetricEnum;
$storagePath = __DIR__ . '/var/vector-store';
// Create the store instance (the directory must exist and be writable)
$store = new JsonFileVectorStore(
$storagePath,
new JsonFileVectorCollectionRepositoryFactory(),
);
// Create a new collection backed by a single JSON file
$store->createCollection('documents', 384, DistanceMetricEnum::COSINE);
// Get a repository for this collection
$repository = $store->getCollection('documents');
Upserting and searching
use AdachSoft\VectorStoreContracts\Collection\FilterCollection;
use AdachSoft\VectorStoreContracts\Collection\FloatVectorCollection;
use AdachSoft\VectorStoreContracts\Collection\MetadataCollection;
use AdachSoft\VectorStoreContracts\Dto\FilterExpressionDto;
use AdachSoft\VectorStoreContracts\Dto\SearchQueryDto;
use AdachSoft\VectorStoreContracts\Dto\VectorRecordDto;
use AdachSoft\VectorStoreContracts\Enum\FilterOperatorEnum;
// Upsert a vector record
$record = new VectorRecordDto(
'doc-123',
// 384-dimensional vector (example values)
new FloatVectorCollection([0.1, 0.2, 0.3, 0.4 /* ... */]),
new MetadataCollection([
'category' => 'technology',
'technologies' => ['php', 'typescript'],
'language' => 'en',
]),
);
$repository->upsert($record);
// Build a search query
$query = new SearchQueryDto(
new FloatVectorCollection([0.11, 0.21, 0.31, 0.41 /* ... */]), // query vector
5, // topK
new FilterCollection(['language' => 'en']),
null, // optional minimum score
);
// Execute the search
$results = $repository->search($query);
foreach ($results as $result) {
$record = $result->record;
$score = $result->score;
// Handle the result (e.g. display ID and score)
}
Batch operations
Use upsertBatch() to insert or replace multiple records and deleteBatch() to remove multiple UUIDs:
use AdachSoft\VectorStoreContracts\Collection\RecordUuidCollection;
use AdachSoft\VectorStoreContracts\Collection\VectorRecordDtoCollection;
$repository->upsertBatch(new VectorRecordDtoCollection([$record]));
$repository->deleteBatch(new RecordUuidCollection(['doc-123', 'doc-456']));
Batch upserts validate every vector dimension before writing; if validation fails, no record in the batch is persisted. Repeated UUIDs in a batch use the last record, and empty batches are no-ops.
Metadata filters
Scalar filter values use the EQUALS operator. Legacy array filter values use
ANY. Use FilterExpressionDto when the operator must be explicit:
$query = new SearchQueryDto(
new FloatVectorCollection([0.11, 0.21, 0.31, 0.41 /* ... */]),
5,
new FilterCollection([
'technologies' => new FilterExpressionDto(
FilterOperatorEnum::ALL,
['php', 'typescript'],
),
]),
null,
);
Metadata values can be scalars or flat indexed or associative arrays containing only scalars. Nested arrays, objects, and null values are not supported.
Concurrent writes
Writes to the same collection are synchronized between cooperating PHP processes on the same host using an exclusive lock file named <collection>.json.lock. Updated documents are written to uniquely named temporary files and atomically renamed into place. Lock files are intentionally left in the storage directory.
Using the factory
If you prefer configuration-based creation, you can use the factory:
use AdachSoft\VectorStoreJsonFile\JsonFileVectorStoreFactory;
$factory = new JsonFileVectorStoreFactory();
$store = $factory->create([
'storage_path' => __DIR__ . '/var/vector-store',
]);
Testing
This project includes a test suite based on the contract tests from
adachsoft/vector-store-contracts.
Run tests with:
vendor/bin/phpunit
The test configuration is defined in phpunit.xml in the project root.
Code style and static analysis
The project uses adachsoft/php-code-style
for a unified code style, Rector rules and PHPStan configuration.
Convenience Composer scripts:
composer cs:check # run PHP-CS-Fixer in dry-run mode
composer cs:fix # fix coding style issues
composer stan # run PHPStan analysis
composer rector # run Rector refactorings
License
This library is open-sourced under the MIT license. See the license field in
composer.json for details.