Skip to content

Commit

Permalink
Array fields support (#81)
Browse files Browse the repository at this point in the history
Fixes #77

(cherry picked from commit b1bd801)
BlackGad authored and roji committed Apr 22, 2024
1 parent 8c025e1 commit 6aea142
Showing 8 changed files with 428 additions and 33 deletions.
137 changes: 137 additions & 0 deletions Milvus.Client.Tests/FieldTests.cs
Original file line number Diff line number Diff line change
@@ -67,4 +67,141 @@ public void CreateFloatVectorTest()
Assert.Equal(2, field.RowCount);
Assert.Equal(2, field.Data.Count);
}

[Fact]
public void CreateInt8ArrayTest()
{
var field = FieldData.CreateArray(
"vector",
new sbyte[][]
{
[1, 2],
[3, 4],
});

Assert.Equal(MilvusDataType.Array, field.DataType);
Assert.Equal(MilvusDataType.Int8, field.ElementType);
Assert.Equal(2, field.RowCount);
Assert.Equal(2, field.Data.Count);
}

[Fact]
public void CreateInt16ArrayTest()
{
var field = FieldData.CreateArray(
"vector",
new short[][]
{
[1, 2],
[3, 4],
});

Assert.Equal(MilvusDataType.Array, field.DataType);
Assert.Equal(MilvusDataType.Int16, field.ElementType);
Assert.Equal(2, field.RowCount);
Assert.Equal(2, field.Data.Count);
}

[Fact]
public void CreateInt32ArrayTest()
{
var field = FieldData.CreateArray(
"vector",
new int[][]
{
[1, 2],
[3, 4],
});

Assert.Equal(MilvusDataType.Array, field.DataType);
Assert.Equal(MilvusDataType.Int32, field.ElementType);
Assert.Equal(2, field.RowCount);
Assert.Equal(2, field.Data.Count);
}

[Fact]
public void CreateInt64ArrayTest()
{
var field = FieldData.CreateArray(
"vector",
new long[][]
{
[1, 2],
[3, 4],
});

Assert.Equal(MilvusDataType.Array, field.DataType);
Assert.Equal(MilvusDataType.Int64, field.ElementType);
Assert.Equal(2, field.RowCount);
Assert.Equal(2, field.Data.Count);
}

[Fact]
public void CreateBoolArrayTest()
{
var field = FieldData.CreateArray(
"vector",
new bool[][]
{
[true, false],
[false, false],
});

Assert.Equal(MilvusDataType.Array, field.DataType);
Assert.Equal(MilvusDataType.Bool, field.ElementType);
Assert.Equal(2, field.RowCount);
Assert.Equal(2, field.Data.Count);
}

[Fact]
public void CreateFloatArrayTest()
{
var field = FieldData.CreateArray(
"vector",
new float[][]
{
[1, 2],
[3, 4],
});

Assert.Equal(MilvusDataType.Array, field.DataType);
Assert.Equal(MilvusDataType.Float, field.ElementType);
Assert.Equal(2, field.RowCount);
Assert.Equal(2, field.Data.Count);
}

[Fact]
public void CreateDoubleArrayTest()
{
var field = FieldData.CreateArray(
"vector",
new double[][]
{
[1, 2],
[3, 4],
});

Assert.Equal(MilvusDataType.Array, field.DataType);
Assert.Equal(MilvusDataType.Double, field.ElementType);
Assert.Equal(2, field.RowCount);
Assert.Equal(2, field.Data.Count);
}

//TODO: differentiate VarChar and String somehow
[Fact]
public void CreateVarCharArrayTest()
{
var field = FieldData.CreateArray(
"vector",
new string[][]
{
["3d4d387208e04a9abe77be65e2b7c7b3", "a5502ddb557047968a70ff69720d2dd2"],
["4c246789a91f4b15aa3b26799df61457", "00a23e95823b4f14854ceed5f7059953"],
});

Assert.Equal(MilvusDataType.Array, field.DataType);
Assert.Equal(MilvusDataType.VarChar, field.ElementType);
Assert.Equal(2, field.RowCount);
Assert.Equal(2, field.Data.Count);
}
}
3 changes: 3 additions & 0 deletions Milvus.Client.sln.DotSettings
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/BLANK_LINES_AROUND_MULTILINE_CASE_SECTION/@EntryValue">1</s:Int64>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_WITHIN_SINGLE_LINE_ARRAY_INITIALIZER_BRACES/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Jaccard/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Milvus/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=pymilvus/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=quantizes/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=quantizing/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=sbytes/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Tanimoto/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=topk/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=upserted/@EntryIndexedValue">True</s:Boolean>
145 changes: 145 additions & 0 deletions Milvus.Client/ArrayFieldData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
namespace Milvus.Client;

/// <summary>
/// Binary Field
/// </summary>
public sealed class ArrayFieldData<TElementData> : FieldData<IReadOnlyList<TElementData>>
{
/// <summary>
/// Construct an array field
/// </summary>
/// <param name="fieldName"></param>
/// <param name="data"></param>
/// <param name="isDynamic"></param>
public ArrayFieldData(string fieldName, IReadOnlyList<IReadOnlyList<TElementData>> data, bool isDynamic)
: base(fieldName, data, MilvusDataType.Array, isDynamic)
{
ElementType = EnsureDataType<TElementData>();
}

/// <summary>
/// Array element type
/// </summary>
public MilvusDataType ElementType { get; }

/// <inheritdoc />
internal override Grpc.FieldData ToGrpcFieldData()
{
Check();

Grpc.FieldData fieldData = new()
{
Type = Grpc.DataType.Array,
IsDynamic = IsDynamic
};

if (FieldName is not null)
{
fieldData.FieldName = FieldName;
}

var arrayArray = new ArrayArray
{
ElementType = (DataType) ElementType,
};

fieldData.Scalars = new ScalarField
{
ArrayData = arrayArray
};

foreach (var array in Data)
{
switch (ElementType)
{
case MilvusDataType.Bool:
BoolArray boolData = new();
boolData.Data.AddRange(array as IEnumerable<bool>);
arrayArray.Data.Add(new ScalarField { BoolData = boolData, });
break;

case MilvusDataType.Int8:
IntArray int8Data = new();
var sbytes = array as IEnumerable<sbyte> ?? Enumerable.Empty<sbyte>();
int8Data.Data.AddRange(sbytes.Select(x => (int) x));
arrayArray.Data.Add(new ScalarField { IntData = int8Data, });
break;

case MilvusDataType.Int16:
IntArray int16Data = new();
var shorts = array as IEnumerable<short> ?? Enumerable.Empty<short>();
int16Data.Data.AddRange(shorts.Select(x => (int) x));
arrayArray.Data.Add(new ScalarField { IntData = int16Data, });
break;

case MilvusDataType.Int32:
IntArray int32Data = new();
int32Data.Data.AddRange(array as IEnumerable<int>);
arrayArray.Data.Add(new ScalarField { IntData = int32Data, });
break;

case MilvusDataType.Int64:
LongArray int64Data = new();
int64Data.Data.AddRange(array as IEnumerable<long>);
arrayArray.Data.Add(new ScalarField { LongData = int64Data, });
break;

case MilvusDataType.Float:
FloatArray floatData = new();
floatData.Data.AddRange(array as IEnumerable<float>);
arrayArray.Data.Add(new ScalarField { FloatData = floatData, });
break;

case MilvusDataType.Double:
DoubleArray doubleData = new();
doubleData.Data.AddRange(array as IEnumerable<double>);
arrayArray.Data.Add(new ScalarField { DoubleData = doubleData, });
break;

case MilvusDataType.String:
StringArray stringData = new();
stringData.Data.AddRange(array as IEnumerable<string>);
arrayArray.Data.Add(new ScalarField { StringData = stringData, });
break;

case MilvusDataType.VarChar:
StringArray varcharData = new();
varcharData.Data.AddRange(array as IEnumerable<string>);
arrayArray.Data.Add(new ScalarField { StringData = varcharData, });
break;

case MilvusDataType.Json:
JSONArray jsonData = new();
var enumerable = array as IEnumerable<string> ?? Enumerable.Empty<string>();
jsonData.Data.AddRange(enumerable.Select(ByteString.CopyFromUtf8));
arrayArray.Data.Add(new ScalarField { JsonData = jsonData, });
break;

case MilvusDataType.None:
throw new MilvusException($"ElementType Error:{DataType}");

default:
throw new MilvusException($"ElementType Error:{DataType}, not supported");
}
}

return fieldData;
}

internal override object GetValueAsObject(int index)
=> ElementType switch
{
MilvusDataType.Bool => ((IReadOnlyList<IEnumerable<bool>>) Data)[index],
MilvusDataType.Int8 => ((IReadOnlyList<IEnumerable<sbyte>>) Data)[index],
MilvusDataType.Int16 => ((IReadOnlyList<IEnumerable<short>>) Data)[index],
MilvusDataType.Int32 => ((IReadOnlyList<IEnumerable<int>>) Data)[index],
MilvusDataType.Int64 => ((IReadOnlyList<IEnumerable<long>>) Data)[index],
MilvusDataType.Float => ((IReadOnlyList<IEnumerable<float>>) Data)[index],
MilvusDataType.Double => ((IReadOnlyList<IEnumerable<double>>) Data)[index],
MilvusDataType.String => ((IReadOnlyList<IEnumerable<string>>) Data)[index],
MilvusDataType.VarChar => ((IReadOnlyList<IEnumerable<string>>) Data)[index],

MilvusDataType.None => throw new MilvusException($"DataType Error:{DataType}"),
_ => throw new MilvusException($"DataType Error:{DataType}, not supported")
};
}
5 changes: 5 additions & 0 deletions Milvus.Client/Constants.cs
Original file line number Diff line number Diff line change
@@ -70,6 +70,11 @@ internal static class Constants
/// </summary>
internal const string FailedReason = "failed_reason";

/// <summary>
/// Key name.
/// </summary>
internal const string MaxCapacity = "max_capacity";

/// <summary>
/// Files.
/// </summary>
96 changes: 66 additions & 30 deletions Milvus.Client/FieldData.cs
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@ public abstract class FieldData
/// </summary>
/// <param name="fieldName">Field name.</param>
/// <param name="dataType">Field data type.</param>
/// <param name="isDynamic"></param>
/// <param name="isDynamic">Whether the field is dynamic.</param>
protected FieldData(string fieldName, MilvusDataType dataType, bool isDynamic = false)
{
FieldName = fieldName;
@@ -120,23 +120,41 @@ internal static FieldData FromGrpcFieldData(Grpc.FieldData fieldData)
}

case Grpc.FieldData.FieldOneofCase.Scalars:
return fieldData.Scalars.DataCase switch
return fieldData.Scalars switch
{
Grpc.ScalarField.DataOneofCase.BoolData
{ DataCase: ScalarField.DataOneofCase.BoolData }
=> Create(fieldData.FieldName, fieldData.Scalars.BoolData.Data, fieldData.IsDynamic),
Grpc.ScalarField.DataOneofCase.FloatData
{ DataCase: ScalarField.DataOneofCase.FloatData }
=> Create(fieldData.FieldName, fieldData.Scalars.FloatData.Data, fieldData.IsDynamic),
Grpc.ScalarField.DataOneofCase.IntData
{ DataCase: ScalarField.DataOneofCase.IntData }
=> Create(fieldData.FieldName, fieldData.Scalars.IntData.Data, fieldData.IsDynamic),
Grpc.ScalarField.DataOneofCase.LongData
{ DataCase: ScalarField.DataOneofCase.LongData }
=> Create(fieldData.FieldName, fieldData.Scalars.LongData.Data, fieldData.IsDynamic),
Grpc.ScalarField.DataOneofCase.StringData
{ DataCase: ScalarField.DataOneofCase.StringData }
=> CreateVarChar(fieldData.FieldName, fieldData.Scalars.StringData.Data, fieldData.IsDynamic),
Grpc.ScalarField.DataOneofCase.JsonData
=> CreateJson(fieldData.FieldName, fieldData.Scalars.JsonData.Data
.Select(p => p.ToStringUtf8()).ToList(), fieldData.IsDynamic),

_ => throw new NotSupportedException($"{fieldData.Scalars.DataCase} not support"),
{ DataCase: ScalarField.DataOneofCase.JsonData }
=> CreateJson(fieldData.FieldName, fieldData.Scalars.JsonData.Data.Select(p => p.ToStringUtf8()).ToList(), fieldData.IsDynamic),
{ DataCase: ScalarField.DataOneofCase.ArrayData, ArrayData.ElementType: Grpc.DataType.Bool }
=> CreateArray(fieldData.FieldName, fieldData.Scalars.ArrayData.Data.Select(x => x.BoolData.Data).ToArray(), fieldData.IsDynamic),
{ DataCase: ScalarField.DataOneofCase.ArrayData, ArrayData.ElementType: Grpc.DataType.Int8 }
=> CreateArray(fieldData.FieldName, fieldData.Scalars.ArrayData.Data.Select(x => x.IntData.Data).ToArray(), fieldData.IsDynamic),
{ DataCase: ScalarField.DataOneofCase.ArrayData, ArrayData.ElementType: Grpc.DataType.Int16 }
=> CreateArray(fieldData.FieldName, fieldData.Scalars.ArrayData.Data.Select(x => x.IntData.Data).ToArray(), fieldData.IsDynamic),
{ DataCase: ScalarField.DataOneofCase.ArrayData, ArrayData.ElementType: Grpc.DataType.Int32 }
=> CreateArray(fieldData.FieldName, fieldData.Scalars.ArrayData.Data.Select(x => x.IntData.Data).ToArray(), fieldData.IsDynamic),
{ DataCase: ScalarField.DataOneofCase.ArrayData, ArrayData.ElementType: Grpc.DataType.Int64 }
=> CreateArray(fieldData.FieldName, fieldData.Scalars.ArrayData.Data.Select(x => x.LongData.Data).ToArray(), fieldData.IsDynamic),
{ DataCase: ScalarField.DataOneofCase.ArrayData, ArrayData.ElementType: Grpc.DataType.Float }
=> CreateArray(fieldData.FieldName, fieldData.Scalars.ArrayData.Data.Select(x => x.FloatData.Data).ToArray(), fieldData.IsDynamic),
{ DataCase: ScalarField.DataOneofCase.ArrayData, ArrayData.ElementType: Grpc.DataType.Double }
=> CreateArray(fieldData.FieldName, fieldData.Scalars.ArrayData.Data.Select(x => x.DoubleData.Data).ToArray(), fieldData.IsDynamic),
{ DataCase: ScalarField.DataOneofCase.ArrayData, ArrayData.ElementType: Grpc.DataType.String }
=> CreateArray(fieldData.FieldName, fieldData.Scalars.ArrayData.Data.Select(x => x.StringData.Data).ToArray(), fieldData.IsDynamic),
{ DataCase: ScalarField.DataOneofCase.ArrayData, ArrayData.ElementType: Grpc.DataType.VarChar }
=> CreateArray(fieldData.FieldName, fieldData.Scalars.ArrayData.Data.Select(x => x.StringData.Data).ToArray(), fieldData.IsDynamic),
{ DataCase: ScalarField.DataOneofCase.ArrayData, ArrayData.ElementType: Grpc.DataType.Json }
=> CreateArray(fieldData.FieldName, fieldData.Scalars.ArrayData.Data.Select(x => x.JsonData.Data).ToArray(), fieldData.IsDynamic),
_ => throw new NotSupportedException($"{ fieldData.Scalars.DataCase } not support"),
};

default:
@@ -147,7 +165,7 @@ internal static FieldData FromGrpcFieldData(Grpc.FieldData fieldData)
internal static MilvusDataType EnsureDataType<TDataType>()
{
Type type = typeof(TDataType);
MilvusDataType dataType = MilvusDataType.Double;
MilvusDataType dataType;

if (type == typeof(bool))
{
@@ -191,7 +209,7 @@ internal static MilvusDataType EnsureDataType<TDataType>()
}
else
{
throw new NotSupportedException($"Not Support DataType:{dataType}");
throw new NotSupportedException($"Type {type.Name} cannot be mapped to DataType");
}

return dataType;
@@ -227,15 +245,30 @@ public static FieldData<TData> Create<TData>(
/// Create a varchar field.
/// </summary>
/// <param name="fieldName">Field name.</param>
/// <param name="data">Data.</param>
/// <param name="isDynamic"></param>
/// <param name="data">Data in this field</param>
/// <param name="isDynamic">Whether the field is dynamic.</param>
/// <returns></returns>
public static FieldData<string> CreateVarChar(
string fieldName,
IReadOnlyList<string> data,
bool isDynamic = false)
=> new(fieldName, data, MilvusDataType.VarChar, isDynamic);

/// <summary>
/// Create array of elements.
/// </summary>
/// <param name="fieldName">Field name.</param>
/// <param name="data">Data in this field</param>
/// <param name="isDynamic">Whether the field is dynamic.</param>
/// <returns></returns>
public static ArrayFieldData<TElement> CreateArray<TElement>(
string fieldName,
IReadOnlyList<IReadOnlyList<TElement>> data,
bool isDynamic = false)
{
return new(fieldName, data, isDynamic);
}

/// <summary>
/// Create a field from <see cref="byte"/> array.
/// </summary>
@@ -267,8 +300,8 @@ public static BinaryVectorFieldData CreateFromBytes(string fieldName, ReadOnlySp
/// <summary>
/// Create a binary vectors
/// </summary>
/// <param name="fieldName"></param>
/// <param name="data"></param>
/// <param name="fieldName">Field name.</param>
/// <param name="data">Data in this field</param>
/// <returns></returns>
public static BinaryVectorFieldData CreateBinaryVectors(string fieldName, IReadOnlyList<ReadOnlyMemory<byte>> data)
{
@@ -281,7 +314,7 @@ public static BinaryVectorFieldData CreateBinaryVectors(string fieldName, IReadO
/// Create a float vector.
/// </summary>
/// <param name="fieldName">Field name.</param>
/// <param name="data">Data</param>
/// <param name="data">Data in this field</param>
/// <returns></returns>
public static FloatVectorFieldData CreateFloatVector(string fieldName, IReadOnlyList<ReadOnlyMemory<float>> data)
=> new(fieldName, data);
@@ -290,7 +323,7 @@ public static FloatVectorFieldData CreateFloatVector(string fieldName, IReadOnly
/// Create a field from stream
/// </summary>
/// <param name="fieldName">Field name</param>
/// <param name="stream"></param>
/// <param name="stream">Stream data</param>
/// <param name="dimension">Dimension of data</param>
/// <returns>New created field</returns>
public static FieldData CreateFromStream(string fieldName, Stream stream, long dimension)
@@ -305,8 +338,8 @@ public static FieldData CreateFromStream(string fieldName, Stream stream, long d
/// Create json field.
/// </summary>
/// <param name="fieldName">Field name.</param>
/// <param name="json">json field.</param>
/// <param name="isDynamic"></param>
/// <param name="json">Json field.</param>
/// <param name="isDynamic">Whether the field is dynamic.</param>
/// <returns></returns>
public static FieldData CreateJson(string fieldName, IReadOnlyList<string> json, bool isDynamic = false)
{
@@ -324,20 +357,20 @@ public class FieldData<TData> : FieldData
/// <summary>
/// Construct a field
/// </summary>
/// <param name="fieldName"></param>
/// <param name="data"></param>
/// <param name="isDynamic"></param>
/// <param name="fieldName">Field name.</param>
/// <param name="data">Data in this field</param>
/// <param name="isDynamic">Whether the field is dynamic.</param>
public FieldData(string fieldName, IReadOnlyList<TData> data, bool isDynamic = false)
: base(fieldName, EnsureDataType<TData>(), isDynamic)
=> Data = data;

/// <summary>
/// Construct a field
/// </summary>
/// <param name="fieldName"></param>
/// <param name="data"></param>
/// <param name="fieldName">Field name.</param>
/// <param name="data">Data in this field</param>
/// <param name="milvusDataType">Milvus data type.</param>
/// <param name="isDynamic"></param>
/// <param name="isDynamic">Whether the field is dynamic.</param>
public FieldData(string fieldName, IReadOnlyList<TData> data, MilvusDataType milvusDataType, bool isDynamic)
: base(fieldName, milvusDataType, isDynamic)
=> Data = data;
@@ -446,7 +479,6 @@ internal override Grpc.FieldData ToGrpcFieldData()
}
fieldData.Scalars = new Grpc.ScalarField { JsonData = jsonData, };
break;

case MilvusDataType.None:
throw new MilvusException($"DataType Error:{DataType}");
default:
@@ -481,7 +513,11 @@ internal override object GetValueAsObject(int index)
public override string ToString()
=> $"Field: {{{nameof(FieldName)}: {FieldName}, {nameof(DataType)}: {DataType}, {nameof(Data)}: {Data?.Count}, {nameof(RowCount)}: {RowCount}}}";

private void Check()
/// <summary>
/// Checks data
/// </summary>
/// <exception cref="MilvusException"></exception>
protected void Check()
{
if (Data.Any() != true)
{
48 changes: 48 additions & 0 deletions Milvus.Client/FieldSchema.cs
Original file line number Diff line number Diff line change
@@ -95,6 +95,42 @@ public static FieldSchema CreateBinaryVector(string name, int dimension, string
public static FieldSchema CreateJson(string name)
=> new(name, MilvusDataType.Json);

/// <summary>
/// Create a field schema for a <c>array</c> of <c>TData</c> field.
/// </summary>
/// <typeparam name="TData">Determines the element data type of array stored in the field based.</typeparam>
/// <param name="name">The field name.</param>
/// <param name="maxCapacity">Maximum number of elements that an array field can contain.</param>
/// <param name="description">An optional description for the field.</param>
public static FieldSchema CreateArray<TData>(
string name,
int maxCapacity,
string description = "")
=> new(name, MilvusDataType.Array, description: description)
{
ElementDataType = FieldData.EnsureDataType<TData>(),
MaxCapacity = maxCapacity,
};

/// <summary>
/// Create a field schema for a <c>array</c> of <c>varchar</c> field.
/// </summary>
/// <param name="name">The field name.</param>
/// <param name="maxCapacity">Maximum number of elements that an array field can contain.</param>
/// <param name="maxLength">Maximum length of strings for each <c>varchar</c> element in an array field.</param>
/// <param name="description">An optional description for the field.</param>
public static FieldSchema CreateVarcharArray(
string name,
int maxCapacity,
int maxLength,
string description = "")
=> new(name, MilvusDataType.Array, description: description)
{
ElementDataType = MilvusDataType.VarChar,
MaxCapacity = maxCapacity,
MaxLength = maxLength,
};

// Construct used when the user constructs a schema to be provided to CreateSchema
private FieldSchema(
string name,
@@ -118,6 +154,7 @@ internal FieldSchema(
long id,
string name,
MilvusDataType dataType,
MilvusDataType elementType,
FieldState state,
bool isPrimaryKey,
bool autoId,
@@ -128,6 +165,7 @@ internal FieldSchema(
FieldId = id;
Name = name;
DataType = dataType;
ElementDataType = elementType;
State = state;
IsPrimaryKey = isPrimaryKey;
AutoId = autoId;
@@ -146,6 +184,11 @@ internal FieldSchema(
/// </summary>
public MilvusDataType DataType { get; }

/// <summary>
/// The element data type for array stored in the field.
/// </summary>
public MilvusDataType ElementDataType { get; set; }

/// <summary>
/// Whether the field is a primary key.
/// </summary>
@@ -187,6 +230,11 @@ internal FieldSchema(
/// </summary>
public int? MaxLength { get; set; }

/// <summary>
/// Maximum number of elements that an array field can contain. Mandatory for <see cref="MilvusDataType.Array" /> fields, and must be in a range [1, 4096]
/// </summary>
public int? MaxCapacity { get; set; }

/// <summary>
/// The dimension of the vector. Mandatory for <see cref="MilvusDataType.FloatVector" />
/// and <see cref="MilvusDataType.BinaryVector" /> fields, and must be greater than zero.
10 changes: 10 additions & 0 deletions Milvus.Client/MilvusClient.Collection.cs
Original file line number Diff line number Diff line change
@@ -87,6 +87,7 @@ public async Task<MilvusCollection> CreateCollectionAsync(
{
Name = field.Name,
DataType = (DataType)(int)field.DataType,
ElementType = (DataType)(int)field.ElementDataType,
IsPrimaryKey = field.IsPrimaryKey,
IsPartitionKey = field.IsPartitionKey,
AutoID = field.AutoId,
@@ -111,6 +112,15 @@ public async Task<MilvusCollection> CreateCollectionAsync(
});
}

if (field.MaxCapacity is not null)
{
grpcField.TypeParams.Add(new Grpc.KeyValuePair
{
Key = Constants.MaxCapacity,
Value = field.MaxCapacity.Value.ToString(CultureInfo.InvariantCulture)
});
}

grpcCollectionSchema.Fields.Add(grpcField);
}

17 changes: 14 additions & 3 deletions Milvus.Client/MilvusCollection.Collection.cs
Original file line number Diff line number Diff line change
@@ -34,9 +34,16 @@ await _client.InvokeAsync(_client.GrpcClient.DescribeCollectionAsync, request, r
foreach (Grpc.FieldSchema grpcField in response.Schema.Fields)
{
FieldSchema milvusField = new(
grpcField.FieldID, grpcField.Name, (MilvusDataType)grpcField.DataType,
(FieldState)grpcField.State, grpcField.IsPrimaryKey, grpcField.AutoID, grpcField.IsPartitionKey,
grpcField.IsDynamic, grpcField.Description);
grpcField.FieldID,
grpcField.Name,
(MilvusDataType) grpcField.DataType,
(MilvusDataType) grpcField.ElementType,
(FieldState) grpcField.State,
grpcField.IsPrimaryKey,
grpcField.AutoID,
grpcField.IsPartitionKey,
grpcField.IsDynamic,
grpcField.Description);

foreach (Grpc.KeyValuePair parameter in grpcField.TypeParams)
{
@@ -46,6 +53,10 @@ await _client.InvokeAsync(_client.GrpcClient.DescribeCollectionAsync, request, r
milvusField.MaxLength = int.Parse(parameter.Value, CultureInfo.InvariantCulture);
break;

case Constants.MaxCapacity:
milvusField.MaxCapacity = int.Parse(parameter.Value, CultureInfo.InvariantCulture);
break;

case Constants.VectorDim:
milvusField.Dimension = int.Parse(parameter.Value, CultureInfo.InvariantCulture);
break;

0 comments on commit 6aea142

Please sign in to comment.