elastic-mapping 0.1.0

Generate Elasticsearch mapping definitions from Rust structs and enums using derive macros
Documentation
# elastic-mapping

[![Crates.io](https://img.shields.io/crates/v/elastic-mapping.svg)](https://crates.io/crates/elastic-mapping)
[![Documentation](https://docs.rs/elastic-mapping/badge.svg)](https://docs.rs/elastic-mapping)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

Generate Elasticsearch mapping definitions from Rust structs and enums using derive macros.

## Features

- **Derive macro** for automatic mapping generation from Rust types
- **Serde compatibility** - respects `#[serde(rename)]`, `#[serde(rename_all)]`, `#[serde(flatten)]` and enum representations
- **Enum support** - handles externally tagged, internally tagged (`#[serde(tag = "...")]`), and adjacently tagged (`#[serde(tag = "...", content = "...")]`) enums
- **Field annotations** - configure analyzers, keyword fields, and other Elasticsearch-specific settings
- **Optional feature flags** - support for `chrono`, `url`, and `uuid` types

## Available Features

- `chrono` - Adds support for `chrono::DateTime<Utc>` (mapped as `date`)
- `url` - Adds support for `url::Url` (mapped as `text`)
- `uuid` - Adds support for `uuid::Uuid` (mapped as `text`)
- `full` - Enables all optional features

## Usage

### Basic Example

```rust
use elastic_mapping::{Document, MappingObject};
use serde::Serialize;

#[derive(Debug, Serialize, Document)]
struct BlogPost {
    title: String,
    content: String,
    published: bool,
    views: i64,
}

fn main() {
    let mapping = BlogPost::document_mapping();
    println!("{}", serde_json::to_string_pretty(mapping.inner()).unwrap());
}
```

Output:

```json
{
  "mappings": {
    "properties": {
      "content": {
        "type": "text"
      },
      "published": {
        "type": "boolean"
      },
      "title": {
        "type": "text"
      },
      "views": {
        "type": "long"
      }
    }
  }
}
```

### Field Annotations

```rust
use elastic_mapping::{Document, MappingObject};

#[derive(Debug, Document)]
struct Article {
    #[document(analyzer = "english")]
    title: String,
    
    #[document(keyword(index = false))]
    internal_id: String,
    
    #[document(keyword(ignore_above = 256))]
    category: String,
}
```

### Serde Compatibility

The macro respects serde attributes:

```rust
use elastic_mapping::{Document, MappingObject};
use serde::Serialize;

#[derive(Debug, Serialize, Document)]
#[serde(rename_all = "camelCase")]
struct UserProfile {
    first_name: String,
    last_name: String,
    email_address: String,
}

// Field names will be mapped as: firstName, lastName, emailAddress
```

### Nested Structures

```rust
use elastic_mapping::{Document, MappingObject};

#[derive(Debug, Document)]
struct Address {
    street: String,
    city: String,
    country: String,
}

#[derive(Debug, Document)]
struct User {
    name: String,
    address: Address,
    tags: Vec<String>,
}
```

### Enum Support

#### Externally Tagged Enums

```rust
use elastic_mapping::{Document, MappingObject};

#[derive(Debug, Document)]
enum Event {
    Created { id: String, timestamp: i64 },
    Updated { id: String, changes: String },
    Deleted { id: String },
}
```

#### Internally Tagged Enums

```rust
use elastic_mapping::{Document, MappingObject};
use serde::Serialize;

#[derive(Debug, Serialize, Document)]
#[serde(tag = "type")]
enum Message {
    Text { content: String },
    Image { url: String, width: u32, height: u32 },
}
```

#### Adjacently Tagged Enums

```rust
use elastic_mapping::{Document, MappingObject};
use serde::Serialize;

#[derive(Debug, Serialize, Document)]
#[serde(tag = "type", content = "data")]
enum Notification {
    Email { to: String, subject: String },
    SMS { phone: String, message: String },
    Push { device_id: String, title: String },
}
```

### Flatten Support

```rust
use elastic_mapping::{Document, MappingObject};
use serde::Serialize;

#[derive(Debug, Serialize, Document)]
struct Metadata {
    created_at: i64,
    updated_at: i64,
}

#[derive(Debug, Serialize, Document)]
struct Document {
    title: String,
    content: String,
    #[serde(flatten)]
    metadata: Metadata,
}

// Fields created_at and updated_at will be flattened into Document
```

### With Optional Features

| Rust Type | Elasticsearch Type | Feature Flag |
|-----------|-------------------|--------------|
| `chrono::DateTime<Utc>` | `date` | `chrono` |
| `url::Url` | `text` | `url` |
| `uuid::Uuid` | `text` | `uuid` |

## Available Attributes

### Field-level `#[document(...)]` Attributes

- `analyzer = "analyzer_name"` - Sets the analyzer for a text field
- `keyword(index = bool)` - Adds a keyword subfield with index configuration
- `keyword(ignore_above = u32)` - Adds a keyword subfield with ignore_above setting

### Serde Attributes

The following serde attributes are respected:

- `#[serde(rename = "name")]` - Rename a field or variant
- `#[serde(rename_all = "case")]` - Rename all fields or variants (supports `camelCase`, `kebab-case`, `snake_case`, `SCREAMING_SNAKE_CASE`, etc.)
- `#[serde(flatten)]` - Flatten nested structure fields
- `#[serde(tag = "...")]` - Internally tagged enum representation
- `#[serde(tag = "...", content = "...")]` - Adjacently tagged enum representation

## License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.