symfony/ai-mongo-db-message-store
MongoDB message store integration for Symfony AI Chat, providing persistent conversation storage through the MongoDB PHP library. Part of the Symfony AI component collection.
composer require symfony/ai-chat symfony/ai-mongo-db-message-store mongodb/mongodb
config/services.yaml (Symfony) or config/mongodb.php (Laravel):
# config/packages/ai.yaml (Symfony)
framework:
ai:
message_store: mongodb
mongodb:
uri: 'mongodb://user:pass@host:port/db'
collection: 'ai_chat_messages'
use MongoDB\Client;
$client = new Client('mongodb://user:pass@host:port/db');
$client->selectDatabase('db')->createCollection('ai_chat_messages');
use Symfony\Component\AI\Chat\MessageStore\MongoDbMessageStore;
use Symfony\Component\AI\Chat\Message;
$store = new MongoDbMessageStore($client->selectDatabase('db'));
$store->save(new Message('user', 'Hello!'));
$messages = $store->findByConversationId('conv_123');
symfony/dependency-injection for container integration.// Laravel Service Example
public function handleChatRequest(string $conversationId, string $userInput): array
{
$store = app(MongoDbMessageStore::class);
$messages = $store->findByConversationId($conversationId);
$response = $this->callSymfonyAIChat($userInput, $messages);
$store->save(new Message('ai', $response));
return ['response' => $response, 'history' => $messages];
}
// TTL Index Setup (via MongoDB CLI or PHP)
$collection->createIndex(['timestamp' => 1], ['expireAfterSeconds' => 2592000]); // 30 days
// Laravel Route
Route::post('/chat', function (Request $request) {
$response = Http::post('http://symfony-ai-service/api/chat', $request->all());
return $response->json();
});
// Laravel Service Provider
public function register()
{
$this->app->singleton(MongoDbMessageStore::class, function ($app) {
$client = new Client(config('mongodb.connection'));
return new MongoDbMessageStore($client->selectDatabase(config('mongodb.database')));
});
}
Symfony\Component\AI\Chat\Event\MessageSentEvent for post-processing:
public function handle(MessageSentEvent $event)
{
// Log, analyze, or sync to CRM
}
$text search for full-text queries:
$messages = $store->findBy([
'conversationId' => 'conv_123',
'text' => ['$text' => ['$search' => 'urgent']]
]);
class ResilientMongoDbMessageStore implements MessageStoreInterface
{
public function __construct(
private MongoDbMessageStore $primary,
private ?MessageStoreInterface $fallback = null
) {}
public function save(Message $message)
{
try {
$this->primary->save($message);
} catch (\Exception $e) {
$this->fallback?->save($message);
}
}
}
Driver Conflicts:
mongodb/mongodb (v2.0+) vs. jenssegers/mongodb (Laravel’s legacy driver).mongodb/mongodb and update Laravel’s MongoDB config:
// config/mongodb.php
'connections' => [
'default' => [
'driver' => 'mongodb',
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', 27017),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'options' => [
'typeMap' => ['root' => 'array', 'document' => 'array'], // Critical for Symfony serialization
],
],
],
Serialization Mismatches:
serializer may conflict with Laravel’s JSON handling.# config/packages/serializer.yaml
framework:
serializer:
mapping:
paths: ['%kernel.project_dir%/config/serializer']
ignore_annotations: true
Missing Indexes:
conversationId or timestamp.$collection->createIndex(['conversationId' => 1, 'timestamp' => -1]);
No Schema Validation:
spatie/laravel-mongodb-schema):
use Spatie\LaravelMongoDbSchema\Schema;
Schema::create('ai_chat_messages', function (Blueprint $collection) {
$collection->index('conversationId');
$collection->index('timestamp');
$collection->required('userId');
$collection->required('role'); // 'user' or 'ai'
$collection->required('content');
});
Symfony-Specific Assumptions:
Message class; Laravel may need adapters.class LaravelMessage implements \Symfony\Component\AI\Chat\MessageInterface
{
public function __construct(
public string $role,
public string $content,
public ?string $id = null,
public ?string $conversationId = null,
public ?\DateTimeInterface $timestamp = null
) {}
}
$client->selectDatabase('db')->manage()->getLogger()->setCallback(function ($level, $message) {
error_log("[MongoDB] [$level] $message");
});
explain() to analyze slow queries:
$explanation = $collection->find(['conversationId' => 'conv_123'])->explain();
InvalidArgumentException: Check typeMap in MongoDB options (must match Symfony’s expectations).ClassNotFoundException: Ensure Symfony\Component\AI\Chat\Message is autoloaded or use the Laravel adapter.class ExtendedMongoDbMessageStore extends MongoDbMessageStore
{
public function saveWithMetadata(Message $message, array $metadata)
{
$document = $this->convertMessageToDocument($message);
$document['metadata'] = $metadata;
$this->collection->insertOne($document);
}
}
class EventfulMongoDbMessageStore extends MongoDbMessageStore
{
public function save(Message $message)
{
$result = parent::save($message);
event(new MessageStored($message, $result->getInsertedId()));
return $result;
}
}
public function bulkSave(iterable $messages)
{
$documents = array_map([$this, 'convertMessageToDocument'], $messages);
$this->collection->insertMany($documents);
}
4
How can I help you explore Laravel packages today?