Observed since 20 Oct, 17:38 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
Core utilities for building MongoDB/Cosmos DB aggregation pipelines
MongoDB aggregation pipeline builders and file operations for record enrichment.
# From PyPI
pip install abs-pipelines-core
# Or with Poetry
poetry add abs-pipelines-core
Use prepare_enrichment() to get everything you need in one call:
from abs_pipelines_core import RecordEnricher
enricher = RecordEnricher(
blob_service=blob_service,
user_collection_name="user_documents"
)
# Fetch ALL fields for the entity
fields = (await field_repository.get_all(filters)).get("founds", [])
# Prepare enrichment config (with optional record filter)
config = enricher.prepare_enrichment(
fields=fields,
record_ids=["rec_id_1", "rec_id_2"], # Optional: filter by specific IDs
option_field_ids=["status_field_id"] # Optional: fields needing label resolution
)
# Apply to query
find = ListFilter()
if config.pre_filter:
find.pre_filters = config.pre_filter
find.reference_fields = AggregationStage(pipeline=config.pipeline)
# Get records
response = await repository.get_all(find, collection_name)
# Add file URLs (post-processing)
response = await enricher.process_file_fields(config.file_field_ids, response)
File upload/download operations for entity records:
from abs_pipelines_core import EntityRecordBlobHandler
# Initialize with blob repository
blob_handler = EntityRecordBlobHandler(blob_repository)
# Upload single file
result = await blob_handler.upload_record_field_file(entity_id, field_id, file)
# Returns: {field_id: file_id}
# Upload multiple files (filename format: {field_id}_actualfilename)
results = await blob_handler.upload_record_field_files(entity_id, files)
# Returns: [{field_id: file_id}, ...]
# Get file URL
url = await blob_handler.get_record_field_file(file_id)
# Get multiple file URLs
urls = await blob_handler.get_record_field_files(entity_id, file_ids)
# Returns: [{file_id: url}, ...]
# Delete file
await blob_handler.delete_record_field_file(file_id)
# Delete field folder
await blob_handler.delete_record_field_folder(entity_id, field_id)
# Delete entity folder
await blob_handler.delete_record_folder(entity_id)
Files are stored with this path structure:
entity-{entity_id}/field-{field_id}/{file_id}Use build_fields_with_associations_pipeline() to fetch fields with their associated definitions populated:
from abs_pipelines_core import build_fields_with_associations_pipeline
# Build the pipeline
pipeline = build_fields_with_associations_pipeline(user_collection_name="users_documents")
# Add a match stage and run
full_pipeline = [{"$match": {"entity_id": entity_id}}, *pipeline]
fields = await db.fields.aggregate(full_pipeline).to_list(1000)
# Result for association field:
# {
# "_id": "field_123",
# "type": "association",
# "reference": {
# "entity_id": "entity_456",
# "entity_fields": [ # <-- Populated!
# {"_id": "...", "name": "Name", "type": "text", ...},
# ]
# }
# }
# Result for user field:
# {
# "_id": "field_789",
# "type": "user",
# "user_filter": {
# "is_active": true,
# "users": [ # <-- Populated!
# {"_id": "...", "name": "John Doe", ...},
# ]
# }
# }
The prepare_enrichment() method returns an EnrichmentConfig with:
| Property | Type | Description |
|---|---|---|
pipeline | List[Dict] | Combined $lookup and $addFields aggregation stages |
pre_filter | Optional[Dict] | Filter schema for record_ids (use with find.pre_filters) |
file_field_ids | List[str] | Field IDs for file URL processing |
build_lookup_pipeline(fields)Build $lookup stages for association and user fields:
lookup_pipeline = enricher.build_lookup_pipeline(fields)
build_option_label_pipeline(field_id, value_to_label, is_multi_select)Build $addFields stage for option label resolution:
value_to_label = {"uuid-1": "Active", "uuid-2": "Inactive"}
option_pipeline = enricher.build_option_label_pipeline(
field_id="status",
value_to_label=value_to_label,
is_multi_select=False
)
process_file_fields(file_fields, response, expiry_minutes)Attach file URLs to records (async, post-processing):
response = await enricher.process_file_fields(
file_fields=["file_field_id"],
response=response,
expiry_minutes=5
)
abs_pipelines_core/
├── __init__.py # Public API exports
├── record_enricher.py # RecordEnricher, schemas, and protocols
├── blob_handler.py # EntityRecordBlobHandler for file operations
└── fields_pipeline.py # build_fields_with_associations_pipeline
from abs_pipelines_core import (
# Record enrichment
RecordEnricher, # Aggregation pipeline builder
EnrichmentConfig, # Return type for prepare_enrichment()
FieldConfig, # Schema for field configurations
FieldReference, # Schema for association references
OptionConfig, # Schema for select options
BlobStorageProtocol, # Protocol for blob service (get_file_url)
# Blob/file operations
EntityRecordBlobHandler, # File operations handler
RequestData, # Request data for file uploads
BlobRepositoryProtocol, # Protocol for full blob repository
# Fields pipeline
build_fields_with_associations_pipeline, # Fields with associations aggregation
)
pypistats · 67 observations shown. Missing days are unknown. Source category: overall: without mirrors.
| Date / source period | Value | Observed at |
|---|---|---|
| 2026-10-20 – 2026-10-20 | 6 | 2026-10-21T12:50:58.2397674Z |
| 2026-10-19 – 2026-10-19 | 9 | 2026-10-21T12:50:58.2397674Z |
| 2026-10-18 – 2026-10-18 | 1 | 2026-10-21T12:50:58.2397674Z |
| 2026-10-16 – 2026-10-16 | 1 | 2026-10-21T12:50:58.2397674Z |
| 2026-10-15 – 2026-10-15 | 2 | 2026-10-21T12:50:58.2397674Z |
| 2026-10-14 – 2026-10-14 | 1 | 2026-10-21T12:50:58.2397674Z |
| 2026-10-13 – 2026-10-13 | 5 | 2026-10-21T12:50:58.2397674Z |
| 2026-10-12 – 2026-10-12 | 1 | 2026-10-21T12:50:58.2397674Z |
| 2026-10-11 – 2026-10-11 | 2 | 2026-10-21T12:50:58.2397674Z |
| 2026-10-09 – 2026-10-09 | 5 | 2026-10-21T12:50:58.2397674Z |
| 2026-10-08 – 2026-10-08 | 13 | 2026-10-21T12:50:58.2397674Z |
| 2026-10-07 – 2026-10-07 | 1 | 2026-10-21T12:50:58.2397674Z |
| 2026-10-06 – 2026-10-06 | 1 | 2026-10-21T12:50:58.2397674Z |
| 2026-10-05 – 2026-10-05 | 1 | 2026-10-21T12:50:58.2397674Z |
| 2026-10-03 – 2026-10-03 | 1 | 2026-10-21T12:50:58.2397674Z |
| 2026-10-01 – 2026-10-01 | 1 | 2026-10-21T12:50:58.2397674Z |
| 2026-09-30 – 2026-09-30 | 2 | 2026-10-21T12:50:58.2397674Z |
| 2026-09-29 – 2026-09-29 | 2 | 2026-10-21T12:50:58.2397674Z |
| 2026-09-28 – 2026-09-28 | 3 | 2026-10-21T12:50:58.2397674Z |
| 2026-09-27 – 2026-09-27 | 1 | 2026-10-21T12:50:58.2397674Z |
| 2026-09-26 – 2026-09-26 | 2 | 2026-10-21T12:50:58.2397674Z |
| 2026-09-25 – 2026-09-25 | 16 | 2026-10-21T12:50:58.2397674Z |
| 2026-09-24 – 2026-09-24 | 1 | 2026-10-21T12:50:58.2397674Z |
| 2026-09-23 – 2026-09-23 | 2 | 2026-10-21T12:50:58.2397674Z |
| 2026-09-20 – 2026-09-20 | 1 | 2026-10-21T12:50:58.2397674Z |
| 2026-09-18 – 2026-09-18 | 4 | 2026-10-21T12:50:58.2397674Z |
| 2026-09-13 – 2026-09-13 | 1 | 2026-10-21T12:50:58.2397674Z |
| 2026-09-12 – 2026-09-12 | 2 | 2026-10-21T12:50:58.2397674Z |
| 2026-09-11 – 2026-09-11 | 4 | 2026-10-21T12:50:58.2397674Z |
| 2026-09-10 – 2026-09-10 | 1 | 2026-10-21T12:50:58.2397674Z |
| 2026-09-09 – 2026-09-09 | 1 | 2026-10-21T12:50:58.2397674Z |
| 2026-09-08 – 2026-09-08 | 1 | 2026-10-21T12:50:58.2397674Z |
| 2026-09-07 – 2026-09-07 | 2 | 2026-10-21T12:50:58.2397674Z |
| 2026-09-06 – 2026-09-06 | 4 | 2026-10-21T12:50:58.2397674Z |
| 2026-09-05 – 2026-09-05 | 3 | 2026-10-21T12:50:58.2397674Z |
| 2026-09-04 – 2026-09-04 | 12 | 2026-10-21T12:50:58.2397674Z |
| 2026-09-03 – 2026-09-03 | 5 | 2026-10-21T12:50:58.2397674Z |
| 2026-09-01 – 2026-09-01 | 6 | 2026-10-21T12:50:58.2397674Z |
| 2026-08-31 – 2026-08-31 | 2 | 2026-10-21T12:50:58.2397674Z |
| 2026-08-28 – 2026-08-28 | 1 | 2026-10-21T12:50:58.2397674Z |
| 2026-08-27 – 2026-08-27 | 2 | 2026-10-21T12:50:58.2397674Z |
| 2026-08-26 – 2026-08-26 | 12 | 2026-10-21T12:50:58.2397674Z |
| 2026-08-25 – 2026-08-25 | 3 | 2026-10-21T12:50:58.2397674Z |
| 2026-08-24 – 2026-08-24 | 20 | 2026-10-21T12:50:58.2397674Z |
| 2026-08-23 – 2026-08-23 | 5 | 2026-10-21T12:50:58.2397674Z |
| 2026-08-21 – 2026-08-21 | 1 | 2026-10-21T12:50:58.2397674Z |
| 2026-08-20 – 2026-08-20 | 3 | 2026-10-21T12:50:58.2397674Z |
| 2026-08-19 – 2026-08-19 | 2 | 2026-10-21T12:50:58.2397674Z |
| 2026-08-18 – 2026-08-18 | 38 | 2026-10-21T12:50:58.2397674Z |
| 2026-08-17 – 2026-08-17 | 6 | 2026-10-21T12:50:58.2397674Z |
| 2026-08-14 – 2026-08-14 | 4 | 2026-10-21T12:50:58.2397674Z |
| 2026-08-13 – 2026-08-13 | 3 | 2026-10-21T12:50:58.2397674Z |
| 2026-08-11 – 2026-08-11 | 4 | 2026-10-21T12:50:58.2397674Z |
| 2026-08-10 – 2026-08-10 | 2 | 2026-10-21T12:50:58.2397674Z |
| 2026-08-09 – 2026-08-09 | 5 | 2026-10-21T12:50:58.2397674Z |
| 2026-08-07 – 2026-08-07 | 4 | 2026-10-21T12:50:58.2397674Z |
| 2026-08-06 – 2026-08-06 | 1 | 2026-10-21T12:50:58.2397674Z |
| 2026-08-04 – 2026-08-04 | 5 | 2026-10-21T12:50:58.2397674Z |
| 2026-08-03 – 2026-08-03 | 10 | 2026-10-21T12:50:58.2397674Z |
| 2026-08-02 – 2026-08-02 | 1 | 2026-10-21T12:50:58.2397674Z |
| 2026-08-01 – 2026-08-01 | 1 | 2026-10-21T12:50:58.2397674Z |
| 2026-07-31 – 2026-07-31 | 1 | 2026-10-21T12:50:58.2397674Z |
| 2026-07-30 – 2026-07-30 | 1 | 2026-10-21T12:50:58.2397674Z |
| 2026-07-29 – 2026-07-29 | 10 | 2026-10-21T12:50:58.2397674Z |
| 2026-07-27 – 2026-07-27 | 2 | 2026-10-21T12:50:58.2397674Z |
| 2026-07-24 – 2026-07-24 | 1 | 2026-10-21T12:50:58.2397674Z |
| 2026-07-23 – 2026-07-23 | 4 | 2026-10-21T12:50:58.2397674Z |
| Version | Published | Direct dependencies | Open version |
|---|---|---|---|
| 0.1.1 | 28 Jan 2026 | 3 |
This describes our collected data; it is not a security assessment.
Observed since 20 Oct, 17:38 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package:297a4338dd146ef947b583515ffbad50386740c8ca3de7e59f10dca8928db9c4