9
9
10
10
#include < atomic>
11
11
#include < jsoncons/json.hpp>
12
+ #include < jsoncons_ext/jsonpath/jsonpath.hpp>
12
13
#include < variant>
13
14
#include < vector>
14
15
@@ -31,16 +32,17 @@ using namespace facade;
31
32
32
33
namespace {
33
34
34
- const absl::flat_hash_map<string_view, search::Schema ::FieldType> kSchemaTypes = {
35
- {" TAG" sv, search::Schema ::TAG},
36
- {" TEXT" sv, search::Schema ::TEXT},
37
- {" NUMERIC" sv, search::Schema ::NUMERIC},
38
- {" VECTOR" sv, search::Schema ::VECTOR}};
35
+ const absl::flat_hash_map<string_view, search::SchemaField ::FieldType> kSchemaTypes = {
36
+ {" TAG" sv, search::SchemaField ::TAG},
37
+ {" TEXT" sv, search::SchemaField ::TEXT},
38
+ {" NUMERIC" sv, search::SchemaField ::NUMERIC},
39
+ {" VECTOR" sv, search::SchemaField ::VECTOR}};
39
40
40
41
static const set<string_view> kIgnoredOptions = {" WEIGHT" , " SEPARATOR" , " TYPE" , " DIM" ,
41
42
" DISTANCE_METRIC" };
42
43
43
- optional<search::Schema> ParseSchemaOrReply (CmdArgList args, ConnectionContext* cntx) {
44
+ optional<search::Schema> ParseSchemaOrReply (DocIndex::DataType type, CmdArgList args,
45
+ ConnectionContext* cntx) {
44
46
search::Schema schema;
45
47
for (size_t i = 0 ; i < args.size (); i++) {
46
48
string_view field = ArgS (args, i);
@@ -49,6 +51,31 @@ optional<search::Schema> ParseSchemaOrReply(CmdArgList args, ConnectionContext*
49
51
return nullopt;
50
52
}
51
53
54
+ // Verify json path is correct
55
+ if (type == DocIndex::JSON) {
56
+ error_code ec;
57
+ jsoncons::jsonpath::make_expression<JsonType>(field, ec);
58
+ if (ec) {
59
+ (*cntx)->SendError (" Bad json path: " + string{field});
60
+ return nullopt;
61
+ }
62
+ }
63
+
64
+ // AS [alias]
65
+ string_view field_alias = field; // by default "alias" is same as identifier
66
+ if (absl::AsciiStrToUpper (ArgS (args, i)) == " AS" ) {
67
+ if (i++ >= args.size ()) {
68
+ (*cntx)->SendError (" Expected attribute for field: " + string{field});
69
+ return nullopt;
70
+ }
71
+ field_alias = ArgS (args, i);
72
+
73
+ if (i++ >= args.size ()) {
74
+ (*cntx)->SendError (" No field type for field: " + string{field});
75
+ return nullopt;
76
+ }
77
+ }
78
+
52
79
ToUpper (&args[i]);
53
80
string_view type_str = ArgS (args, i);
54
81
auto it = kSchemaTypes .find (type_str);
@@ -58,15 +85,15 @@ optional<search::Schema> ParseSchemaOrReply(CmdArgList args, ConnectionContext*
58
85
}
59
86
60
87
// Skip {algorithm} {dim} flags
61
- if (it->second == search::Schema ::VECTOR)
88
+ if (it->second == search::SchemaField ::VECTOR)
62
89
i += 2 ;
63
90
64
91
// Skip all trailing ignored parameters
65
92
while (i + 2 < args.size () && kIgnoredOptions .count (ArgS (args, i + 1 )) > 0 ) {
66
93
i += 2 ;
67
94
}
68
95
69
- schema.fields [field ] = it->second ;
96
+ schema.fields [field_alias ] = {string{field}, it->second } ;
70
97
}
71
98
72
99
return schema;
@@ -174,7 +201,7 @@ void ReplyKnn(size_t knn_limit, const SearchParams& params, absl::Span<SearchRes
174
201
}
175
202
}
176
203
177
- string_view GetSchemaTypeName (search::Schema ::FieldType type) {
204
+ string_view GetSchemaTypeName (search::SchemaField ::FieldType type) {
178
205
for (const auto & [iname, itype] : kSchemaTypes ) {
179
206
if (itype == type)
180
207
return iname;
@@ -225,7 +252,7 @@ void SearchFamily::FtCreate(CmdArgList args, ConnectionContext* cntx) {
225
252
if (i++ >= args.size ())
226
253
return (*cntx)->SendError (" Empty schema" );
227
254
228
- auto schema = ParseSchemaOrReply (args.subspan (i), cntx);
255
+ auto schema = ParseSchemaOrReply (index. type , args.subspan (i), cntx);
229
256
if (!schema)
230
257
return ;
231
258
index.schema = move (*schema);
@@ -278,7 +305,7 @@ void SearchFamily::FtInfo(CmdArgList args, ConnectionContext* cntx) {
278
305
if (num_notfound > 0u )
279
306
return (*cntx)->SendError (" Unknown index name" );
280
307
281
- DCHECK (infos.front ().schema .fields == infos.back ().schema .fields );
308
+ DCHECK_EQ (infos.front ().schema .fields . size (), infos.back ().schema .fields . size () );
282
309
283
310
size_t total_num_docs = 0 ;
284
311
for (const auto & info : infos)
@@ -292,8 +319,10 @@ void SearchFamily::FtInfo(CmdArgList args, ConnectionContext* cntx) {
292
319
(*cntx)->SendSimpleString (" fields" );
293
320
const auto & fields = infos.front ().schema .fields ;
294
321
(*cntx)->StartArray (fields.size ());
295
- for (auto [field, type] : fields) {
296
- string_view reply[3 ] = {string_view{field}, " type" sv, GetSchemaTypeName (type)};
322
+ for (const auto & [field_name, field_info] : fields) {
323
+ string_view reply[6 ] = {" identifier" , string_view{field_info.identifier },
324
+ " attribute" , string_view{field_name},
325
+ " type" sv, GetSchemaTypeName (field_info.type )};
297
326
(*cntx)->SendSimpleStrArr (reply);
298
327
}
299
328
0 commit comments