Repository: dbpunk-labs/db3 (language: rust)

Issue:
requiring an index id is not friendly when creating a colleciont
## Motivations

```
db3>-$ new-collection --addr 0xbb8115fc82991117e2ed8ec170ca9106c3b95b2f --name todos --index '{"name":"owner","fields":[{"field_path":"owner","value_mode":{"Order":1}}]}'
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Error("missing field `id`", line: 1, column: 75)', src/cmd/src/command.rs:479:72
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

```
- Would you like to implement this feature? [y/n]

## Solution

<!-- Describe the solution you'd like. -->

## Alternatives

<!-- Describe any alternative solutions or features you've considered. -->

## Additional context

<!-- Add any other context or screenshots about the feature request here. -->



Discussion / hints:

Fix patch:
diff --git a/src/base/src/bson_util.rs b/src/base/src/bson_util.rs
index 85014018..c37c026a 100644
--- a/src/base/src/bson_util.rs
+++ b/src/base/src/bson_util.rs
@@ -9,6 +9,7 @@ use db3_proto::db3_database_proto::structured_query::value::ValueType;
 use db3_proto::db3_database_proto::structured_query::FieldFilter;
 use db3_proto::db3_database_proto::structured_query::Filter;
 use db3_proto::db3_database_proto::structured_query::Value;
+use db3_proto::db3_database_proto::{index::IndexField, Index};
 use serde_json::Value as JsonValue;
 /// convert json string to Bson::Document
 pub fn json_str_to_bson_document(json_str: &str) -> std::result::Result<Document, DB3Error> {
@@ -18,6 +19,26 @@ pub fn json_str_to_bson_document(json_str: &str) -> std::result::Result<Document
         bson::to_document(&value).map_err(|e| DB3Error::InvalidDocumentBytes(format!("{}", e)))?;
     Ok(bson_document)
 }
+pub fn json_str_to_index(json_str: &str, idx: u32) -> std::result::Result<Index, DB3Error> {
+    let value: JsonValue =
+        serde_json::from_str(json_str).map_err(|e| DB3Error::InvalidJson(format!("{}", e)))?;
+
+    if let Some(name) = value.get("name") {
+        if let Some(fields) = value.get("fields") {
+            return Ok(Index {
+                id: idx,
+                name: name.as_str().unwrap().to_string(),
+                fields: fields
+                    .as_array()
+                    .unwrap()
+                    .iter()
+                    .map(|field| serde_json::from_value::<IndexField>(field.clone()).unwrap())
+                    .collect(),
+            });
+        }
+    }
+    Err(DB3Error::InvalidJson(format!("")))
+}
 
 pub fn json_str_to_bson_bytes(json_str: &str) -> std::result::Result<Vec<u8>, DB3Error> {
     match json_str_to_bson_document(json_str) {
@@ -205,6 +226,7 @@ mod tests {
     };
     use bson::Bson;
     use chrono::Utc;
+    use db3_proto::db3_database_proto::index::index_field::{Order, ValueMode};
     #[test]
     fn json_str_to_bson_document_ut() {
         let data = r#"
@@ -446,4 +468,39 @@ mod tests {
             .unwrap()
         );
     }
+    #[test]
+    fn json_str_to_index_ut() {
+        let json_str = r#"{"name":"idx1","fields":[{"field_path":"name","value_mode":{"Order":1}}, {"field_path":"age","value_mode":{"Order":1}}]}"#;
+        let res = json_str_to_index(json_str, 1);
+        assert!(res.is_ok());
+        let index = res.unwrap();
+        println!("{:?}", index);
+        let expect = Index {
+            id: 1,
+            name: "idx1".to_string(),
+            fields: vec![
+                IndexField {
+                    field_path: "name".to_string(),
+                    value_mode: Some(ValueMode::Order(Order::Ascending as i32)),
+                },
+                IndexField {
+                    field_path: "age".to_string(),
+                    value_mode: Some(ValueMode::Order(Order::Ascending as i32)),
+                },
+            ],
+        };
+        assert_eq!(expect, index);
+    }
+    #[test]
+    fn json_str_to_index_wrong_path_1_ut() {
+        let json_str = r#"{"fields":[{"field_path":"name","value_mode":{"Order":1}}, {"field_path":"age","value_mode":{"Order":1}}]}"#;
+        let res = json_str_to_index(json_str, 1);
+        assert!(res.is_err());
+    }
+    #[test]
+    fn json_str_to_index_wrong_path_2_ut() {
+        let json_str = r#"{"name": "idx1""#;
+        let res = json_str_to_index(json_str, 1);
+        assert!(res.is_err());
+    }
 }
diff --git a/src/cmd/src/command.rs b/src/cmd/src/command.rs
index 141d9b7e..d049b81d 100644
--- a/src/cmd/src/command.rs
+++ b/src/cmd/src/command.rs
@@ -488,10 +488,14 @@ impl DB3ClientCommand {
                 index_list,
             } => {
                 //TODO validate the index
-                let index_vec: Vec<Index> = index_list
-                    .iter()
-                    .map(|i| serde_json::from_str::<Index>(i.as_str()).unwrap())
-                    .collect();
+                // .map(|i| serde_json::from_str::<Index>(i.as_str()).unwrap())
+
+                let mut index_vec: Vec<Index> = vec![];
+                for idx in 0..index_list.len() {
+                    index_vec.push(
+                        bson_util::json_str_to_index(index_list[idx].as_str(), idx as u32).unwrap(),
+                    );
+                }
                 let collection = CollectionMutation {
                     index: index_vec.to_owned(),
                     collection_name: name.to_string(),
diff --git a/src/crypto/src/db3_keypair.rs b/src/crypto/src/db3_keypair.rs
index b7aaa3ce..8e9bae30 100644
--- a/src/crypto/src/db3_keypair.rs
+++ b/src/crypto/src/db3_keypair.rs
@@ -175,8 +175,6 @@ mod tests {
     use crate::db3_signature::DB3Signature;
     use crate::key_derive;
     use bip39::{Language, Mnemonic, Seed};
-    use fastcrypto::hash::{HashFunction, Sha3_256};
-    use hex;
     #[test]
     fn keypair_smoke_test_secp256k1() {
         let mnemonic = Mnemonic::from_phrase(
diff --git a/src/node/src/command.rs b/src/node/src/command.rs
index 9c5c6574..f58ce69b 100644
--- a/src/node/src/command.rs
+++ b/src/node/src/command.rs
@@ -613,9 +613,11 @@ mod tests {
             addr: addr.clone(),
             name: collection_books.to_string(),
             index_list: vec![
-                r#"{"id":1,"name":"idx1","fields":[{"field_path":"name","value_mode":{"Order":1}}]}"#.to_string(),
-                r#"{"id":2,"name":"idx2","fields":[{"field_path":"age","value_mode":{"Order":1}}]}"#.to_string(),
-            ]
+                r#"{"name":"idx1","fields":[{"field_path":"name","value_mode":{"Order":1}}]}"#
+                    .to_string(),
+                r#"{"name":"idx2","fields":[{"field_path":"age","value_mode":{"Order":1}}]}"#
+                    .to_string(),
+            ],
         };
 
         if let Ok(_) = cmd.execute(&mut ctx).await {
@@ -629,7 +631,10 @@ mod tests {
         let cmd = DB3ClientCommand::NewCollection {
             addr: addr.clone(),
             name: collection_student.to_string(),
-            index_list: vec![r#"{"id":1,"name":"idx1","fields":[{"field_path":"name","value_mode":{"Order":1}}]}"#.to_string()]
+            index_list: vec![
+                r#"{"name":"idx1","fields":[{"field_path":"name","value_mode":{"Order":1}}]}"#
+                    .to_string(),
+            ],
         };
 
         if let Ok(_) = cmd.execute(&mut ctx).await {


Test patch: