Skip to content

Conversation

@xXAvoraXx
Copy link
Contributor

CHANGELOG

Added Comprehensive CouchDB Partitioned Database Support

This pull request adds full support for CouchDB 3.0+ partitioned databases and enhances the changes feed with design document filter query parameters.

🎯 Overview

Total Changes: 12 files changed, 734 insertions(+), 9 deletions(-)
Commits: 6 commits (excluding initial plan)
Tests Added: 9 comprehensive unit tests


🚀 New Features

1. Partitioned Database Query Operations

Added 4 new public methods to ICouchDatabase<TSource>:

  • GetPartitionInfoAsync(string partitionKey, CancellationToken)

    • Retrieves partition metadata including document count, deleted document count, and size information
    • Maps to GET /{db}/_partition/{key}
  • QueryPartitionAsync(string partitionKey, string mangoQueryJson, CancellationToken)

    • Executes Mango queries scoped to a specific partition using JSON string
    • Maps to POST /{db}/_partition/{key}/_find
  • QueryPartitionAsync(string partitionKey, object mangoQuery, CancellationToken)

    • Executes Mango queries scoped to a specific partition using object selector
    • Maps to POST /{db}/_partition/{key}/_find
  • GetPartitionAllDocsAsync(string partitionKey, CancellationToken)

    • Fetches all documents within a specific partition with attachments initialized
    • Maps to GET /{db}/_partition/{key}/_all_docs

Implementation Details:

  • Partition keys are URL-encoded for safe transmission
  • All parameters are null-checked using existing Check.NotNull() pattern
  • Documents have attachments automatically initialized
  • Follows existing code patterns and conventions

2. Design Document Filter Query Parameters for Changes Feed

New capability to pass custom query parameters to design document filters:

  • ChangesFeedOptions.QueryParameters property

    • Type: Dictionary<string, string>?
    • Allows passing custom parameters to filter functions
    • Parameters accessible in filter functions via req.query
  • ChangesFeedFilter.DesignDocument(string filterName, Dictionary<string, string>? queryParameters)

    • New factory method for creating design document filters
    • Supports optional query parameters
    • Validates filter name is not null or empty

Use Case: Enables efficient partition-based change tracking using design document filters, which is significantly more performant than selector filters for partitioned databases.


📦 New Types

CouchPartitionInfo (sealed class)

Properties:

  • DbName - Database name
  • DocCount - Number of documents in partition
  • DocDelCount - Number of deleted documents
  • Partition - Partition key
  • Sizes - Size information (active, external)

DatabaseProps (sealed class)

Properties:

  • Partitioned - Boolean indicating if database is partitioned

AllDocsResult<T> (internal class)

Internal DTO for _all_docs API responses with nested row structure

DesignDocumentChangesFeedFilter (internal class)

Internal filter type for design document filters with query parameters


🔧 Enhancements

Enhanced CouchDatabaseInfo

  • Added Props property of type DatabaseProps
  • Allows detection of whether a database is partitioned

Enhanced Changes Feed Implementation

  • Added ApplyChangesFeedOptions() helper method to reduce code duplication
  • Added ApplyDesignDocumentFilterParams() helper method for reusable filter logic
  • Both GetChangesAsync() and GetContinuousChangesAsync() now support custom query parameters

🧪 Testing

New Test Files

Partition_Tests.cs (6 tests):

  1. GetPartitionInfo - Tests partition metadata retrieval
  2. QueryPartitionWithJson - Tests JSON string query
  3. QueryPartitionWithObject - Tests object-based query
  4. GetPartitionAllDocs - Tests fetching all partition documents
  5. GetPartitionInfo_WithSpecialCharacters - Tests URL encoding
  6. GetDatabaseInfo_WithPartitionedProperty - Tests database partitioned detection

ChangesFeed_DesignDocumentFilter_Tests.cs (3 tests):

  1. GetChangesAsync_WithDesignDocumentFilter_AppliesFilterName - Tests basic filter application
  2. GetChangesAsync_WithDesignDocumentFilterAndQueryParams_AppliesParameters - Tests filter with parameters
  3. GetChangesAsync_WithOptionsQueryParameters_AppliesParameters - Tests parameters via options

All tests use Flurl's HttpTest for mocking, consistent with existing test patterns.


📚 Documentation

README Updates

New Section: "Partitioned Databases"

  • Creating partitioned databases
  • Document ID format requirements (partition:id)
  • Getting partition information
  • Querying within partitions
  • Checking if database is partitioned
  • Partitioned vs global indexes

Enhanced Section: "Feed Filter"

  • Added DesignDocument filter documentation
  • Comprehensive examples of design document filters with query parameters
  • Design document filter function examples
  • Both inline filter and options-based parameter passing examples

🏗️ Code Quality

Architectural Consistency

  • ✅ Interface + Implementation pattern maintained
  • ✅ Async/await with CancellationToken support throughout
  • ConfigureAwait(false) on all async calls
  • ✅ Flurl fluent API pattern preserved
  • ✅ Private helper methods for internal logic
  • ✅ Consistent DTO structure with internal visibility
  • ✅ XML documentation on all public APIs

Input Validation

  • ✅ Parameter null checks using existing Check.NotNull() helper
  • ✅ Filter name validation in DesignDocumentChangesFeedFilter
  • ✅ Argument validation with descriptive error messages

Code Organization

  • ✅ Extracted duplicate logic into helper methods
  • ✅ Reduced code duplication between sync and async methods
  • ✅ Clear separation of concerns

Security

  • ✅ Passed CodeQL security analysis (0 vulnerabilities)
  • ✅ Proper URL encoding of partition keys
  • ✅ No SQL injection risks
  • ✅ Safe parameter handling

🔄 API Compatibility

Breaking Changes: None - All changes are additive

New Public APIs:

  • ICouchDatabase<TSource>.GetPartitionInfoAsync()
  • ICouchDatabase<TSource>.QueryPartitionAsync() (2 overloads)
  • ICouchDatabase<TSource>.GetPartitionAllDocsAsync()
  • ChangesFeedOptions.QueryParameters property
  • ChangesFeedFilter.DesignDocument() static factory method

Enhanced Types:

  • CouchDatabaseInfo.Props property added

📋 Usage Examples

Partitioned Database Operations

// Create partitioned database
var db = await client.CreateDatabaseAsync<MyDoc>("mydb", partitioned: true);

// Add document with partition key
await db.AddAsync(new MyDoc { Id = "user123:profile" });

// Query within partition
var docs = await db.QueryPartitionAsync("user123", new {
    selector = new { status = "active" }
});

// Get partition metadata
var info = await db.GetPartitionInfoAsync("user123");

Design Document Filter with Query Parameters

// Using filter object
var filter = ChangesFeedFilter.DesignDocument("replication/by_partition", 
    new Dictionary<string, string> { { "partition", "user123" } });

await foreach (var change in db.GetContinuousChangesAsync(null, filter, ct))
{
    // Process partition-scoped changes
}

// Using options
var options = new ChangesFeedOptions
{
    Filter = "replication/by_partition",
    QueryParameters = new Dictionary<string, string> { { "partition", "user123" } }
};
var changes = await db.GetChangesAsync(options);

🎯 Compatibility

  • CouchDB Version: 3.0+ (partitioned databases introduced in 3.0)
  • .NET Target: netstandard2.1
  • Backwards Compatible: Yes (purely additive changes)

📊 Metrics

  • Files Modified: 12
  • Lines Added: 734
  • Lines Removed: 9
  • New Public APIs: 5
  • New Internal Types: 4
  • Unit Tests Added: 9
  • Documentation Sections Added: 2

✅ Quality Checklist

  • All tests passing
  • Code review feedback addressed
  • Security scan passed (0 vulnerabilities)
  • Documentation updated
  • Backwards compatible
  • Follows existing code patterns
  • Input validation implemented
  • Error handling consistent
  • XML documentation complete

Copilot AI and others added 7 commits November 22, 2025 13:42
Co-authored-by: xXAvoraXx <6988989+xXAvoraXx@users.noreply.github.com>
Co-authored-by: xXAvoraXx <6988989+xXAvoraXx@users.noreply.github.com>
Co-authored-by: xXAvoraXx <6988989+xXAvoraXx@users.noreply.github.com>
Co-authored-by: xXAvoraXx <6988989+xXAvoraXx@users.noreply.github.com>
Co-authored-by: xXAvoraXx <6988989+xXAvoraXx@users.noreply.github.com>
Add CouchDB partitioned database query operations and design document filter query parameters
@xXAvoraXx
Copy link
Contributor Author

@matteobortolazzo We have a multi-tenant application. Instead of creating a separate database for each business, we aim to reduce costs and improve performance by using the partitioned feature. However, partitioned support in your library is quite limited. Could you review the changes made?

@matteobortolazzo
Copy link
Owner

Thank you! This week I'll give a look at all PRs and issues and try to release a new version

@matteobortolazzo matteobortolazzo changed the base branch from master to dev December 1, 2025 10:18
@matteobortolazzo matteobortolazzo merged commit d3f7751 into matteobortolazzo:dev Dec 1, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants