Browse Source

feat: better experience for editing entity (#748)

Signed-off-by: ryjiang <jiangruiyi@gmail.com>
ryjiang 5 months ago
parent
commit
b94d7b621a

+ 1 - 0
client/src/hooks/Query.ts

@@ -168,6 +168,7 @@ export const useQuery = (params: {
       queryState.collection,
       queryState.collection,
       queryState.consistencyLevel,
       queryState.consistencyLevel,
       queryState.expr,
       queryState.expr,
+      queryState.tick,
     ]),
     ]),
   ]);
   ]);
 
 

+ 1 - 1
client/src/i18n/cn/dialog.ts

@@ -30,7 +30,7 @@ const dialogTrans = {
   flushDialogInfo: `落盘是一个在数据被插入到Milvus后,封闭和索引任何剩余段的过程。这避免了在未封闭的段上进行暴力搜索。  <br /><br />最好在插入会话结束时使用落盘,以防止数据碎片化。 <br /><br /><strong>注意:对于大型数据集,此操作可能需要一些时间。</strong>`,
   flushDialogInfo: `落盘是一个在数据被插入到Milvus后,封闭和索引任何剩余段的过程。这避免了在未封闭的段上进行暴力搜索。  <br /><br />最好在插入会话结束时使用落盘,以防止数据碎片化。 <br /><br /><strong>注意:对于大型数据集,此操作可能需要一些时间。</strong>`,
   emptyDataDialogInfo: `您正在尝试清空数据。此操作无法撤销,请谨慎操作。`,
   emptyDataDialogInfo: `您正在尝试清空数据。此操作无法撤销,请谨慎操作。`,
   resetPropertyInfo: '您确定要重置属性吗?',
   resetPropertyInfo: '您确定要重置属性吗?',
-  editEntityInfo: `注意:编辑id字段将创建一个新的实体。`,
+  editEntityInfo: `注意:编辑PrimayKey字段将会创建一个新的实体。`,
   editAnalyzerInfo: `分析器以JSON格式定义,请参考milvus.io 了解<a href='https://milvus.io/docs/analyzer-overview.md' target='_blank'>更多信息</a>。`,
   editAnalyzerInfo: `分析器以JSON格式定义,请参考milvus.io 了解<a href='https://milvus.io/docs/analyzer-overview.md' target='_blank'>更多信息</a>。`,
 };
 };
 
 

+ 1 - 1
client/src/i18n/en/dialog.ts

@@ -28,7 +28,7 @@ const dialogTrans = {
   flushDialogInfo: `Flush is a process that seals and indexes any remaining segments after data is upserted into Milvus. This avoids brute force searches on unsealed segments.  <br /><br />It's best to use flush at the end of an upsert session to prevent data fragmentation. <br /><br /><strong>Note: that this operation may take some time for large datasets.</strong>`,
   flushDialogInfo: `Flush is a process that seals and indexes any remaining segments after data is upserted into Milvus. This avoids brute force searches on unsealed segments.  <br /><br />It's best to use flush at the end of an upsert session to prevent data fragmentation. <br /><br /><strong>Note: that this operation may take some time for large datasets.</strong>`,
   emptyDataDialogInfo: `You are attempting to empty the data. This action cannot be undone, please proceed with caution.`,
   emptyDataDialogInfo: `You are attempting to empty the data. This action cannot be undone, please proceed with caution.`,
   resetPropertyInfo: `Are you sure you want to reset the property?`,
   resetPropertyInfo: `Are you sure you want to reset the property?`,
-  editEntityInfo: `NOTE: Edit id field will create a new entity.`,
+  editEntityInfo: `NOTE: Edit PrimayKey field will create a new entity.`,
   editAnalyzerInfo: `Analyzer is defined in JSON format, please refer to milvus.io for <a href='https://milvus.io/docs/analyzer-overview.md' target='_blank'>more information</a>.`,
   editAnalyzerInfo: `Analyzer is defined in JSON format, please refer to milvus.io for <a href='https://milvus.io/docs/analyzer-overview.md' target='_blank'>more information</a>.`,
 };
 };
 
 

+ 1 - 0
client/src/pages/databases/Databases.tsx

@@ -235,6 +235,7 @@ const Databases = () => {
               fields: fields,
               fields: fields,
               outputFields: fields.map(f => f.name),
               outputFields: fields.map(f => f.name),
               consistencyLevel: ConsistencyLevelEnum.Bounded,
               consistencyLevel: ConsistencyLevelEnum.Bounded,
+              tick: 0,
             },
             },
           ];
           ];
         });
         });

+ 24 - 9
client/src/pages/databases/collections/data/CollectionData.tsx

@@ -87,6 +87,7 @@ const CollectionData = (props: CollectionDataProps) => {
         ...collection.schema.fields,
         ...collection.schema.fields,
         ...collection.schema.dynamicFields,
         ...collection.schema.dynamicFields,
       ].map(f => f.name),
       ].map(f => f.name),
+      tick: queryState.tick + 1,
     });
     });
 
 
     // ensure not loading
     // ensure not loading
@@ -160,13 +161,19 @@ const CollectionData = (props: CollectionDataProps) => {
     await fetchCollection(collectionName);
     await fetchCollection(collectionName);
   };
   };
 
 
-  const onEditEntity = async () => {
-    await query(
-      currentPage,
-      ConsistencyLevelEnum.Strong,
-      queryState.outputFields,
-      queryState.expr
-    );
+  const onEditEntity = async (id: string) => {
+    // deselect all
+    setSelectedData([]);
+    const newExpr = `${collection.schema.primaryField.name} == ${id}`;
+    // update local expr
+    setExprInput(newExpr);
+    // set expr with id
+    setQueryState({
+      ...queryState,
+      consistencyLevel: ConsistencyLevelEnum.Strong,
+      expr: newExpr,
+      tick: queryState.tick + 1,
+    });
   };
   };
 
 
   // Toolbar settings
   // Toolbar settings
@@ -403,7 +410,11 @@ const CollectionData = (props: CollectionDataProps) => {
                   },
                   },
                   onKeyDown: (e: any) => {
                   onKeyDown: (e: any) => {
                     if (e.key === 'Enter') {
                     if (e.key === 'Enter') {
-                      setQueryState({ ...queryState, expr: exprInput });
+                      setQueryState({
+                        ...queryState,
+                        expr: exprInput,
+                        tick: queryState.tick + 1,
+                      });
                       // reset page
                       // reset page
                       setCurrentPage(0);
                       setCurrentPage(0);
                       e.preventDefault();
                       e.preventDefault();
@@ -498,7 +509,11 @@ const CollectionData = (props: CollectionDataProps) => {
                 onClick={() => {
                 onClick={() => {
                   setCurrentPage(0);
                   setCurrentPage(0);
                   // set expr
                   // set expr
-                  setQueryState({ ...queryState, expr: exprInput });
+                  setQueryState({
+                    ...queryState,
+                    expr: exprInput,
+                    tick: queryState.tick + 1,
+                  });
                 }}
                 }}
                 disabled={!collection.loaded}
                 disabled={!collection.loaded}
               >
               >

+ 1 - 0
client/src/pages/databases/types.ts

@@ -69,4 +69,5 @@ export type QueryState = {
   consistencyLevel: string;
   consistencyLevel: string;
   fields: FieldObject[];
   fields: FieldObject[];
   outputFields: string[];
   outputFields: string[];
+  tick: number;
 };
 };

+ 12 - 7
client/src/pages/dialogs/EditEntityDialog.tsx

@@ -23,15 +23,17 @@ const useStyles = makeStyles((theme: Theme) => ({
     overflow: 'auto',
     overflow: 'auto',
   },
   },
   tip: {
   tip: {
-    fontSize: 12,
-    marginBottom: 8,
+    fontSize: 14,
+    marginBottom: 16,
+    fontWeight: 'bold',
+    color: theme.palette.warning.main,
   },
   },
 }));
 }));
 
 
 type EditEntityDialogProps = {
 type EditEntityDialogProps = {
   data: { [key: string]: any };
   data: { [key: string]: any };
   collection: CollectionFullObject;
   collection: CollectionFullObject;
-  cb?: () => void;
+  cb?: (id: string) => void;
 };
 };
 
 
 // json linter for cm
 // json linter for cm
@@ -71,7 +73,7 @@ const EditEntityDialog: FC<EditEntityDialogProps> = props => {
     sortedData = { ...sortedData, ...data[DYNAMIC_FIELD] };
     sortedData = { ...sortedData, ...data[DYNAMIC_FIELD] };
   }
   }
 
 
-  const originalData = JSON.stringify(sortedData, null, 4);
+  const originalData = JSON.stringify(sortedData, null, 2);
 
 
   // create editor
   // create editor
   useEffect(() => {
   useEffect(() => {
@@ -134,11 +136,14 @@ const EditEntityDialog: FC<EditEntityDialogProps> = props => {
 
 
   // handle confirm
   // handle confirm
   const handleConfirm = async () => {
   const handleConfirm = async () => {
-    await DataService.upsert(collection.collection_name, {
+    const result = (await DataService.upsert(collection.collection_name, {
       fields_data: [JSON.parse(editor.current?.state.doc.toString()!)],
       fields_data: [JSON.parse(editor.current?.state.doc.toString()!)],
-    });
+    })) as any;
 
 
-    props.cb && props.cb();
+    const idField = result.IDs.id_field;
+    const id = result.IDs[idField].data;
+
+    props.cb && props.cb(id[0]);
     handleCloseDialog();
     handleCloseDialog();
   };
   };