README.md•7.69 kB
# Elasticsearch Search Library
A simple, configuration-driven Elasticsearch search library for ITSM entities.
## Features
- **Simple API**: Clean, intuitive interface for entity searches
- **XML Configuration**: Entity-level settings with field-specific configurations
- **11 Entity Types**: Support for all ITSM entity types
- **Conditional Queries**: Automatic query type selection based on fuzziness
- **Type Safety**: Dataclass-based models for configuration and results
- **Async Support**: Full async/await support for search operations
## Quick Start
### Installation
The library is part of your project. No additional installation needed.
### Basic Usage
```python
from elasticsearch_search_lib import SearchClient
# Create search client
client = SearchClient(tenant_id="apolo")
# Search for users
results = await client.search("user", "john doe", limit=10)
# Access results
print(f"Found {results.total_hits} users")
for item in results.items:
    print(f"Name: {item.data['user_name']}, Score: {item.score}")
```
### Search Different Entity Types
```python
# Search impacts
results = await client.search("impact", "High")
# Search locations
results = await client.search("location", "Building A")
# Search vendors
results = await client.search("vendor", "Microsoft")
```
## Supported Entity Types
The library supports 11 ITSM entity types:
### Simple Entities (name, id)
- `impact` - Impact levels
- `urgency` - Urgency levels
- `priority` - Priority levels
### Model-Based Entities (name, id, model)
- `status` - Status values
- `category` - Categories
- `source` - Sources
### Hierarchical Entities (hierarchy, parent/child)
- `location` - Locations with hierarchy
- `department` - Departments with hierarchy
### Complex Entities (multiple fields)
- `usergroup` - User groups
- `user` - Users (name, email, contact, etc.)
- `vendor` - Vendors
## Configuration
### Entity-Level Settings
Each entity has its own configuration in `config/search_config.xml`:
```xml
<entity type="user">
    <fuzziness>AUTO</fuzziness>
    <defaultLimit>10</defaultLimit>
    <maxLimit>100</maxLimit>
    <minScore>0.0</minScore>
    <fields>
        <!-- Field configurations -->
    </fields>
</entity>
```
**Settings:**
- `fuzziness`: Fuzzy matching tolerance (0, 1, 2, AUTO)
- `defaultLimit`: Default number of results
- `maxLimit`: Maximum allowed results
- `minScore`: Minimum relevance score threshold
### Field-Level Settings
Each field can have its own configuration:
```xml
<field>
    <name>user_name</name>
    <boost>3.0</boost>
    <enabled>true</enabled>
    <fuzziness>AUTO</fuzziness>
</field>
```
**Settings:**
- `name`: Field name in Elasticsearch
- `boost`: Relevance boost multiplier
- `enabled`: Whether field is included in searches
- `fuzziness`: Field-specific fuzziness (overrides entity default)
## API Reference
### SearchClient
Main client for entity searches.
#### Constructor
```python
SearchClient(
    tenant_id: str,
    es_host: Optional[str] = None,
    es_port: int = 9200,
    config_path: Optional[str] = None
)
```
**Parameters:**
- `tenant_id`: Tenant identifier for index naming
- `es_host`: Elasticsearch host (defaults to ES_HOST env var or 'localhost')
- `es_port`: Elasticsearch port (default: 9200)
- `config_path`: Path to configuration file (uses default if None)
#### Methods
##### search()
```python
async def search(
    entity_type: str,
    query: str,
    limit: Optional[int] = None,
    from_offset: int = 0
) -> SearchResponse
```
Search for entities.
**Parameters:**
- `entity_type`: Type of entity to search
- `query`: Search query string
- `limit`: Maximum results (uses entity default if None)
- `from_offset`: Offset for pagination
**Returns:** `SearchResponse` object
##### get_supported_entities()
```python
def get_supported_entities() -> List[str]
```
Get list of supported entity types.
##### get_entity_config()
```python
def get_entity_config(entity_type: str) -> EntityConfig
```
Get configuration for an entity type.
##### get_entity_fields()
```python
def get_entity_fields(entity_type: str) -> List[FieldConfig]
```
Get enabled fields for an entity type.
##### is_entity_supported()
```python
def is_entity_supported(entity_type: str) -> bool
```
Check if an entity type is supported.
### SearchResponse
Response object from search operations.
**Attributes:**
- `success`: Whether search was successful
- `entity_type`: Entity type that was searched
- `query`: Search query string
- `total_hits`: Total number of matching documents
- `returned_count`: Number of results in this response
- `items`: List of `SearchResult` objects
- `index_name`: Elasticsearch index that was searched
- `error`: Error message (if search failed)
**Methods:**
- `to_dict()`: Convert to dictionary
- `__len__()`: Get number of results
- `__iter__()`: Iterate over results
- `__getitem__(index)`: Get result by index
### SearchResult
Single search result item.
**Attributes:**
- `data`: Source data from Elasticsearch document
- `score`: Relevance score
- `index`: Index name where document was found
- `id`: Document ID
**Methods:**
- `get(key, default)`: Get value from data dictionary
- `to_dict()`: Convert to dictionary
## Query Strategy
The library uses conditional query types based on fuzziness:
### Exact Matching (fuzziness = 0)
Uses `match_phrase` for exact phrase matching:
```json
{
  "match_phrase": {
    "user_email": {
      "query": "john@example.com",
      "boost": 2.5
    }
  }
}
```
### Fuzzy Matching (fuzziness > 0)
Uses `match` with fuzziness for tolerant matching:
```json
{
  "match": {
    "user_name": {
      "query": "john doe",
      "fuzziness": "AUTO",
      "boost": 3.0
    }
  }
}
```
## Error Handling
The library provides custom exceptions:
```python
from elasticsearch_search_lib.exceptions import (
    SearchLibraryError,      # Base exception
    ConfigurationError,      # Configuration errors
    EntityNotFoundError,     # Entity type not found
    SearchExecutionError,    # Search execution errors
    ValidationError,         # Input validation errors
)
try:
    results = await client.search("user", "john")
except EntityNotFoundError as e:
    print(f"Entity not found: {e}")
except SearchExecutionError as e:
    print(f"Search failed: {e}")
except SearchLibraryError as e:
    print(f"Library error: {e}")
```
## Examples
### Pagination
```python
# Get first page
page1 = await client.search("user", "john", limit=10, from_offset=0)
# Get second page
page2 = await client.search("user", "john", limit=10, from_offset=10)
```
### Check Entity Support
```python
if client.is_entity_supported("user"):
    results = await client.search("user", "john")
else:
    print("User entity not supported")
```
### Get Entity Configuration
```python
config = client.get_entity_config("user")
print(f"Default limit: {config.default_limit}")
print(f"Max limit: {config.max_limit}")
print(f"Min score: {config.min_score}")
```
### Get Entity Fields
```python
fields = client.get_entity_fields("user")
for field in fields:
    print(f"{field.name}: boost={field.boost}, fuzziness={field.fuzziness}")
```
## Architecture
```
elasticsearch_search_lib/
├── __init__.py           # Public API
├── client.py             # SearchClient
├── query_builder.py      # Query construction
├── search_handler.py     # Search execution
├── models.py             # Data models
├── exceptions.py         # Custom exceptions
└── config/
    ├── loader.py         # Configuration loader
    └── search_config.xml # Entity configurations
```
## License
Internal ITSM project library.