sdk/cosmos/azure_data_cosmos/src/models/indexing_policy.rs (287 lines of code) (raw):

// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. use serde::{Deserialize, Serialize}; /// Represents the indexing policy for a container. /// /// For more information see <https://learn.microsoft.com/azure/cosmos-db/index-policy> #[derive(Clone, Default, Debug, Deserialize, Serialize, PartialEq, Eq)] #[serde(rename_all = "camelCase")] pub struct IndexingPolicy { /// Indicates that the indexing policy is automatic. #[serde(default)] pub automatic: bool, /// The indexing mode in use. #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] pub indexing_mode: Option<IndexingMode>, /// The paths to be indexed. #[serde(default)] #[serde(skip_serializing_if = "Vec::is_empty")] pub included_paths: Vec<PropertyPath>, /// The paths to be excluded. #[serde(default)] #[serde(skip_serializing_if = "Vec::is_empty")] pub excluded_paths: Vec<PropertyPath>, /// A list of spatial indexes in the container. #[serde(default)] #[serde(skip_serializing_if = "Vec::is_empty")] pub spatial_indexes: Vec<SpatialIndex>, /// A list of composite indexes in the container #[serde(default)] #[serde(skip_serializing_if = "Vec::is_empty")] pub composite_indexes: Vec<CompositeIndex>, /// A list of vector indexes in the container #[serde(default)] #[serde(skip_serializing_if = "Vec::is_empty")] pub vector_indexes: Vec<VectorIndex>, } /// Defines the indexing modes supported by Azure Cosmos DB. #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] #[serde(rename_all = "camelCase")] pub enum IndexingMode { Consistent, None, } /// Represents a JSON path. #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] #[serde(rename_all = "camelCase")] pub struct PropertyPath { // The path to the property referenced in this index. pub path: String, } impl<T: Into<String>> From<T> for PropertyPath { fn from(value: T) -> Self { PropertyPath { path: value.into() } } } /// Represents a spatial index #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] #[serde(rename_all = "camelCase")] pub struct SpatialIndex { /// The path to the property referenced in this index. pub path: String, /// The spatial types used in this index pub types: Vec<SpatialType>, } /// Defines the types of spatial data that can be indexed. #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] #[serde(rename_all = "PascalCase")] pub enum SpatialType { Point, Polygon, LineString, MultiPolygon, } /// Represents a composite index #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] #[serde(transparent)] pub struct CompositeIndex { /// The properties in this composite index pub properties: Vec<CompositeIndexProperty>, } /// Describes a single property in a composite index. #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] #[serde(rename_all = "camelCase")] pub struct CompositeIndexProperty { /// The path to the property referenced in this index. pub path: String, /// The order of the composite index. /// /// For example, if you want to run the query "SELECT * FROM c ORDER BY c.age asc, c.height desc", /// then you'd specify the order for "/asc" to be *ascending* and the order for "/height" to be *descending*. pub order: CompositeIndexOrder, } /// Ordering values available for composite indexes. #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] #[serde(rename_all = "camelCase")] pub enum CompositeIndexOrder { Ascending, Descending, } /// Represents a vector index /// /// For more information, see <https://learn.microsoft.com/en-us/azure/cosmos-db/index-policy#vector-indexes> #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] #[serde(rename_all = "camelCase")] pub struct VectorIndex { /// The path to the property referenced in this index. pub path: String, /// The type of the vector index. #[serde(rename = "type")] // "type" is a reserved word in Rust. pub index_type: VectorIndexType, } /// Types of vector indexes supported by Cosmos DB #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] #[serde(rename_all = "camelCase")] pub enum VectorIndexType { /// Represents the `flat` vector index type. Flat, /// Represents the `quantizedFlat` vector index type. QuantizedFlat, /// Represents the `diskANN` vector index type. DiskANN, } #[cfg(test)] mod tests { use crate::models::{ CompositeIndex, CompositeIndexOrder, CompositeIndexProperty, IndexingMode, IndexingPolicy, PropertyPath, SpatialIndex, SpatialType, VectorIndex, VectorIndexType, }; #[test] pub fn deserialize_indexing_policy() { // A fairly complete deserialization test that covers most of the indexing policies described in our docs. let policy = r#" { "indexingMode": "consistent", "includedPaths": [ { "path": "/*" } ], "excludedPaths": [ { "path": "/path/to/single/excluded/property/?" }, { "path": "/path/to/root/of/multiple/excluded/properties/*" } ], "spatialIndexes": [ { "path": "/path/to/geojson/property/?", "types": [ "Point", "Polygon", "MultiPolygon", "LineString" ] } ], "vectorIndexes": [ { "path": "/vector1", "type": "quantizedFlat" }, { "path": "/vector2", "type": "diskANN" } ], "compositeIndexes":[ [ { "path":"/name", "order":"ascending" }, { "path":"/age", "order":"descending" } ], [ { "path":"/name2", "order":"descending" }, { "path":"/age2", "order":"ascending" } ] ], "extraValueNotCurrentlyPresentInModel": { "this": "should not fail" } } "#; let policy: IndexingPolicy = serde_json::from_str(policy).unwrap(); assert_eq!( IndexingPolicy { automatic: false, indexing_mode: Some(IndexingMode::Consistent), included_paths: vec![PropertyPath { path: "/*".to_string(), }], excluded_paths: vec![ PropertyPath { path: "/path/to/single/excluded/property/?".to_string() }, PropertyPath { path: "/path/to/root/of/multiple/excluded/properties/*".to_string() }, ], spatial_indexes: vec![SpatialIndex { path: "/path/to/geojson/property/?".to_string(), types: vec![ SpatialType::Point, SpatialType::Polygon, SpatialType::MultiPolygon, SpatialType::LineString, ] }], composite_indexes: vec![ CompositeIndex { properties: vec![ CompositeIndexProperty { path: "/name".to_string(), order: CompositeIndexOrder::Ascending, }, CompositeIndexProperty { path: "/age".to_string(), order: CompositeIndexOrder::Descending, }, ] }, CompositeIndex { properties: vec![ CompositeIndexProperty { path: "/name2".to_string(), order: CompositeIndexOrder::Descending, }, CompositeIndexProperty { path: "/age2".to_string(), order: CompositeIndexOrder::Ascending, }, ] }, ], vector_indexes: vec![ VectorIndex { path: "/vector1".to_string(), index_type: VectorIndexType::QuantizedFlat, }, VectorIndex { path: "/vector2".to_string(), index_type: VectorIndexType::DiskANN, } ] }, policy ); } #[test] pub fn serialize_indexing_policy() { let policy = IndexingPolicy { automatic: true, indexing_mode: None, included_paths: vec![PropertyPath { path: "/*".to_string(), }], excluded_paths: vec![ PropertyPath { path: "/path/to/single/excluded/property/?".to_string(), }, PropertyPath { path: "/path/to/root/of/multiple/excluded/properties/*".to_string(), }, ], spatial_indexes: vec![ SpatialIndex { path: "/path/to/geojson/property/?".to_string(), types: vec![ SpatialType::Point, SpatialType::Polygon, SpatialType::MultiPolygon, SpatialType::LineString, ], }, SpatialIndex { path: "/path/to/geojson/property2/?".to_string(), types: vec![], }, ], composite_indexes: vec![ CompositeIndex { properties: vec![ CompositeIndexProperty { path: "/name".to_string(), order: CompositeIndexOrder::Ascending, }, CompositeIndexProperty { path: "/age".to_string(), order: CompositeIndexOrder::Descending, }, ], }, CompositeIndex { properties: vec![] }, ], vector_indexes: vec![ VectorIndex { path: "/vector1".to_string(), index_type: VectorIndexType::QuantizedFlat, }, VectorIndex { path: "/vector2".to_string(), index_type: VectorIndexType::DiskANN, }, ], }; let json = serde_json::to_string(&policy).unwrap(); assert_eq!( "{\"automatic\":true,\"includedPaths\":[{\"path\":\"/*\"}],\"excludedPaths\":[{\"path\":\"/path/to/single/excluded/property/?\"},{\"path\":\"/path/to/root/of/multiple/excluded/properties/*\"}],\"spatialIndexes\":[{\"path\":\"/path/to/geojson/property/?\",\"types\":[\"Point\",\"Polygon\",\"MultiPolygon\",\"LineString\"]},{\"path\":\"/path/to/geojson/property2/?\",\"types\":[]}],\"compositeIndexes\":[[{\"path\":\"/name\",\"order\":\"ascending\"},{\"path\":\"/age\",\"order\":\"descending\"}],[]],\"vectorIndexes\":[{\"path\":\"/vector1\",\"type\":\"quantizedFlat\"},{\"path\":\"/vector2\",\"type\":\"diskANN\"}]}", json ); } }