ConvergeERP.Shared.Search.Contracts
0.0.2-beta
dotnet add package ConvergeERP.Shared.Search.Contracts --version 0.0.2-beta
NuGet\Install-Package ConvergeERP.Shared.Search.Contracts -Version 0.0.2-beta
<PackageReference Include="ConvergeERP.Shared.Search.Contracts" Version="0.0.2-beta" />
<PackageVersion Include="ConvergeERP.Shared.Search.Contracts" Version="0.0.2-beta" />
<PackageReference Include="ConvergeERP.Shared.Search.Contracts" />
paket add ConvergeERP.Shared.Search.Contracts --version 0.0.2-beta
#r "nuget: ConvergeERP.Shared.Search.Contracts, 0.0.2-beta"
#:package ConvergeERP.Shared.Search.Contracts@0.0.2-beta
#addin nuget:?package=ConvergeERP.Shared.Search.Contracts&version=0.0.2-beta&prerelease
#tool nuget:?package=ConvergeERP.Shared.Search.Contracts&version=0.0.2-beta&prerelease
ConvergeERP.Search.Contracts
Shared contracts and event models for publishing search events to the ConvergeERP Search Service. This package contains all the event definitions, field types, and routing keys needed to integrate any service with the centralized search infrastructure.
Features
- Event Models: Strongly-typed events for entity CRUD operations
- Schema Definitions: Field definitions with type information, indexing, and sensitivity markers
- Routing Constants: Predefined routing keys for message broker integration
- Search Operators: Standard operators for building search queries
Installation
dotnet add package ConvergeERP.Search.Contracts
Events
EntityCreatedEvent
Published when a new entity is created and should be indexed.
var createdEvent = new EntityCreatedEvent
{
EntityType = "Product",
EntityId = product.Id.ToString(),
TenantId = tenantId,
SourceService = "ProductService",
Data = new Dictionary<string, object?>
{
["Name"] = product.Name,
["SKU"] = product.SKU,
["Price"] = product.Price
},
Schema = new Dictionary<string, FieldDefinition>
{
["Name"] = new FieldDefinition { Name = "Name", Type = FieldTypes.String, Searchable = true },
["SKU"] = new FieldDefinition { Name = "SKU", Type = FieldTypes.String, Indexed = true },
["Price"] = new FieldDefinition { Name = "Price", Type = FieldTypes.Decimal, Sensitive = true }
},
// Audit fields
UserId = currentUser.UserId,
UserName = currentUser.Name,
UserEmail = currentUser.Email,
CompanyId = currentUser.CompanyId
};
EntityUpdatedEvent
Published when an entity is modified.
var updatedEvent = new EntityUpdatedEvent
{
EntityType = "Product",
EntityId = product.Id.ToString(),
TenantId = tenantId,
SourceService = "ProductService",
Data = new Dictionary<string, object?>
{
["Name"] = product.Name,
["Price"] = product.Price
},
Version = product.Version, // For optimistic concurrency
ChangedFields = ["Name", "Price"], // Optional: for partial updates
UserId = currentUser.UserId
};
EntityDeletedEvent
Published when an entity is removed.
var deletedEvent = new EntityDeletedEvent
{
EntityType = "Product",
EntityId = product.Id.ToString(),
TenantId = tenantId,
SourceService = "ProductService",
SoftDelete = true, // true = mark inactive, false = remove from index
UserId = currentUser.UserId
};
EntityBulkIndexEvent
Published to trigger bulk indexing (initial sync or recovery).
var bulkEvent = new EntityBulkIndexEvent
{
EntityType = "Product",
TenantId = tenantId,
SourceService = "ProductService",
ClearExisting = true, // Clear before indexing
Items = products.Select(p => new BulkIndexItem
{
EntityId = p.Id.ToString(),
Data = new Dictionary<string, object?>
{
["Name"] = p.Name,
["Price"] = p.Price
}
}).ToList()
};
Field Definitions
Define field metadata for the search service:
var schema = new Dictionary<string, FieldDefinition>
{
["Name"] = new FieldDefinition
{
Name = "Name",
Type = FieldTypes.String,
Searchable = true,
Indexed = true,
DisplayName = "Product Name"
},
["Status"] = new FieldDefinition
{
Name = "Status",
Type = FieldTypes.Enum,
EnumValues = ["Draft", "Active", "Archived"],
Operators = [SearchOperators.Equal, SearchOperators.In]
},
["CategoryId"] = new FieldDefinition
{
Name = "CategoryId",
Type = FieldTypes.Guid,
IsRelationship = true,
RelatedEntityType = "Category",
ForeignKeyProperty = "CategoryId",
EmbedFields = ["Name"], // Embed category name in product search results
CascadeUpdates = true // Update product when category changes
}
};
Field Types
| Type | Constant | Description |
|---|---|---|
string |
FieldTypes.String |
Text fields |
int |
FieldTypes.Integer |
32-bit integers |
long |
FieldTypes.Long |
64-bit integers |
decimal |
FieldTypes.Decimal |
Precise decimals |
double |
FieldTypes.Double |
Floating point |
bool |
FieldTypes.Boolean |
Boolean values |
date |
FieldTypes.Date |
Date only |
datetime |
FieldTypes.DateTime |
Date and time |
enum |
FieldTypes.Enum |
Enumerated values |
guid |
FieldTypes.Guid |
Unique identifiers |
collection |
FieldTypes.Collection |
Arrays/lists |
object |
FieldTypes.Object |
Nested objects |
Routing Keys
Use these constants for message broker integration:
// Exchange
SearchEventRoutingKeys.Exchange // "search.events"
// Entity Events
SearchEventRoutingKeys.EntityCreated // "entity.created"
SearchEventRoutingKeys.EntityUpdated // "entity.updated"
SearchEventRoutingKeys.EntityDeleted // "entity.deleted"
SearchEventRoutingKeys.EntityBulkIndex // "entity.bulk"
// Subscribe to all entity events
SearchEventRoutingKeys.AllEntityEvents // "entity.*"
Search Operators
Available operators for each field type:
// Get default operators for a field type
var stringOps = SearchOperators.GetDefaultOperators(FieldTypes.String);
// ["equals", "notEquals", "contains", "startsWith", "endsWith", "in", "notIn", "isNull", "isNotNull"]
var numericOps = SearchOperators.GetDefaultOperators(FieldTypes.Integer);
// ["equals", "notEquals", "greaterThan", "lessThan", "between", "in", "notIn"]
Operator Constants
| Operator | Constant | Applicable Types |
|---|---|---|
equals |
SearchOperators.Equal |
All |
notEquals |
SearchOperators.NotEqual |
All |
contains |
SearchOperators.Contains |
String, Collection |
startsWith |
SearchOperators.StartsWith |
String |
endsWith |
SearchOperators.EndsWith |
String |
greaterThan |
SearchOperators.GreaterThan |
Numeric, Date |
lessThan |
SearchOperators.LessThan |
Numeric, Date |
between |
SearchOperators.Between |
Numeric, Date |
in |
SearchOperators.In |
All |
notIn |
SearchOperators.NotIn |
All |
isNull |
SearchOperators.IsNull |
All |
isEmpty |
SearchOperators.IsEmpty |
String, Collection |
Audit Fields
All events include audit information via ISearchableEvent:
| Property | Type | Description |
|---|---|---|
UserId |
Guid? |
User who performed the action |
UserName |
string? |
User's display name |
UserEmail |
string? |
User's email |
CompanyId |
Guid? |
Company context (multi-company tenants) |
TenantId |
string |
Tenant identifier |
SourceService |
string |
Publishing service name |
Timestamp |
DateTime |
When the event occurred |
CorrelationId |
string? |
For distributed tracing |
Integration Example
RabbitMQ Publisher
public class RabbitMqSearchPublisher
{
private readonly IConnection _connection;
public async Task PublishAsync<T>(string routingKey, T @event) where T : ISearchableEvent
{
using var channel = await _connection.CreateChannelAsync();
await channel.ExchangeDeclareAsync(
SearchEventRoutingKeys.Exchange,
ExchangeType.Topic,
durable: true);
var body = JsonSerializer.SerializeToUtf8Bytes(@event);
await channel.BasicPublishAsync(
exchange: SearchEventRoutingKeys.Exchange,
routingKey: routingKey,
body: body);
}
}
MassTransit Consumer
public class EntityCreatedConsumer : IConsumer<EntityCreatedEvent>
{
private readonly ISearchIndex _searchIndex;
public async Task Consume(ConsumeContext<EntityCreatedEvent> context)
{
var @event = context.Message;
await _searchIndex.IndexAsync(
entityType: @event.EntityType,
entityId: @event.EntityId,
tenantId: @event.TenantId,
data: @event.Data,
schema: @event.Schema);
}
}
Related Packages
- ConvergeERP.Shared.Search.Interceptors - EF Core interceptor for automatic event publishing
- ConvergeERP.Shared.Search.Schemas - Schema registration service for startup publishing
License
MIT
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- ConvergeERP.Shared.EventBus (>= 0.0.1-beta)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on ConvergeERP.Shared.Search.Contracts:
| Package | Downloads |
|---|---|
|
ConvergeERP.Shared.Search.Interceptors
EF Core SaveChanges interceptor for automatically publishing search events when entities are created, updated, or deleted. Features automatic schema generation, change tracking, soft-delete detection, and multi-tenant support via ICurrentUser. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.0.2-beta | 271 | 6/20/2026 |
| 0.0.1-beta | 1,028 | 3/28/2026 |