KevinStephenson
Adding in weaviate code
b110593
raw
history blame
10.2 kB
// _ _
// __ _____ __ ___ ___ __ _| |_ ___
// \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \
// \ V V / __/ (_| |\ V /| | (_| | || __/
// \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___|
//
// Copyright © 2016 - 2024 Weaviate B.V. All rights reserved.
//
// CONTACT: [email protected]
//
package v1
import (
"github.com/pkg/errors"
"github.com/weaviate/weaviate/entities/models"
"github.com/weaviate/weaviate/entities/schema"
"github.com/weaviate/weaviate/entities/search"
pb "github.com/weaviate/weaviate/grpc/generated/protocol/v1"
"google.golang.org/protobuf/runtime/protoimpl"
)
func parseArray[T float64 | bool | string](v interface{}, innerDt schema.DataType) (*pb.Value, error) {
if _, ok := v.([]interface{}); ok {
return &pb.Value{Kind: &pb.Value_ListValue{ListValue: &pb.ListValue{Values: []*pb.Value{}}}}, nil
}
val, ok := v.([]T)
if !ok {
return nil, protoimpl.X.NewError("invalid type: %T when serializing %v", v, innerDt.String())
}
list, err := NewPrimitiveList(val, innerDt)
if err != nil {
return nil, errors.Wrapf(err, "serializing array with type %v", innerDt)
}
return NewListValue(list), nil
}
func NewPrimitiveValue(v interface{}, dt schema.DataType) (*pb.Value, error) {
innerDt, ok := schema.IsArrayType(dt)
if ok {
switch dt {
case schema.DataTypeBooleanArray:
return parseArray[bool](v, innerDt)
case schema.DataTypeDateArray:
return parseArray[string](v, innerDt)
case schema.DataTypeNumberArray:
return parseArray[float64](v, innerDt)
case schema.DataTypeIntArray:
return parseArray[float64](v, innerDt)
case schema.DataTypeStringArray:
return parseArray[string](v, innerDt)
case schema.DataTypeTextArray:
return parseArray[string](v, innerDt)
case schema.DataTypeUUIDArray:
return parseArray[string](v, innerDt)
default:
return nil, protoimpl.X.NewError("invalid type: %T", v)
}
} else {
switch dt {
case schema.DataTypeBoolean:
val, ok := v.(bool)
if !ok {
return nil, protoimpl.X.NewError("invalid type: %T expected bool when serializing bool", v)
}
return NewBoolValue(val), nil
case schema.DataTypeDate:
val, ok := v.(string)
if !ok {
return nil, protoimpl.X.NewError("invalid type: %T expected string when serializing date", v)
}
return NewDateValue(val), nil
case schema.DataTypeNumber:
val, ok := v.(float64)
if !ok {
return nil, protoimpl.X.NewError("invalid type: %T expected float64 when serializing number", v)
}
return NewNumberValue(val), nil
case schema.DataTypeInt:
val, ok := v.(float64)
if !ok { // integers are returned as float64 from search
return nil, protoimpl.X.NewError("invalid type: %T expected float64 when serializing int property", v)
}
return NewIntValue(int64(val)), nil
case schema.DataTypeString:
val, ok := v.(string)
if !ok {
return nil, protoimpl.X.NewError("invalid type: %T expected string when serializing string property", v)
}
return NewStringValue(val), nil
case schema.DataTypeText:
val, ok := v.(string)
if !ok {
return nil, protoimpl.X.NewError("invalid type: %T expected string when serializing text property", v)
}
return NewStringValue(val), nil
case schema.DataTypeUUID:
val, ok := v.(string)
if !ok {
return nil, protoimpl.X.NewError("invalid type: %T expected string when serializing uuid property", v)
}
return NewUuidValue(val), nil
case schema.DataTypeGeoCoordinates:
val, ok := v.(*models.GeoCoordinates)
if !ok {
return nil, protoimpl.X.NewError("invalid type: %T expected *models.GeoCoordinates when serializing geocoordinate property", v)
}
return NewGeoValue(val), nil
case schema.DataTypeBlob:
val, ok := v.(string)
if !ok {
return nil, protoimpl.X.NewError("invalid type: %T expected string when serializing blob property", v)
}
return NewBlobValue(val), nil
case schema.DataTypePhoneNumber:
val, ok := v.(*models.PhoneNumber)
if !ok {
return nil, protoimpl.X.NewError("invalid type: %T expected *models.PhoneNumber when serializing phone number property", v)
}
return NewPhoneNumberValue(val), nil
default:
return nil, protoimpl.X.NewError("invalid type: %T", v)
}
}
}
func NewNestedValue[P schema.PropertyInterface](v interface{}, dt schema.DataType, parent P, prop search.SelectProperty) (*pb.Value, error) {
switch dt {
case schema.DataTypeObject:
if _, ok := v.(map[string]interface{}); !ok {
return nil, protoimpl.X.NewError("invalid type: %T expected map[string]interface{}", v)
}
obj, err := NewObject(v.(map[string]interface{}), parent, prop)
if err != nil {
return nil, errors.Wrap(err, "creating nested object")
}
return NewObjectValue(obj), nil
case schema.DataTypeObjectArray:
if _, ok := v.([]interface{}); !ok {
return nil, protoimpl.X.NewError("invalid type: %T expected []map[string]interface{}", v)
}
list, err := NewObjectList(v.([]interface{}), parent, prop)
if err != nil {
return nil, errors.Wrap(err, "creating nested object array")
}
return NewListValue(list), nil
default:
return nil, protoimpl.X.NewError("invalid type: %T", v)
}
}
// NewStruct constructs a Struct from a general-purpose Go map.
// The map keys must be valid UTF-8.
// The map values are converted using NewValue.
func NewObject[P schema.PropertyInterface](v map[string]interface{}, parent P, selectProp search.SelectProperty) (*pb.Properties, error) {
if !selectProp.IsObject {
return nil, errors.New("select property is not an object")
}
x := &pb.Properties{Fields: make(map[string]*pb.Value, len(v))}
for _, selectProp := range selectProp.Props {
dt, err := schema.GetNestedPropertyDataType(parent, selectProp.Name)
if err != nil {
return nil, errors.Wrapf(err, "getting data type of nested property %s", selectProp.Name)
}
if *dt == schema.DataTypeObject || *dt == schema.DataTypeObjectArray {
nested, err := schema.GetNestedPropertyByName(parent, selectProp.Name)
if err != nil {
return nil, errors.Wrapf(err, "getting nested property %s", selectProp.Name)
}
x.Fields[selectProp.Name], err = NewNestedValue(v[selectProp.Name], *dt, &NestedProperty{NestedProperty: nested}, selectProp)
if err != nil {
return nil, errors.Wrapf(err, "creating nested object value %s", selectProp.Name)
}
} else {
x.Fields[selectProp.Name], err = NewPrimitiveValue(v[selectProp.Name], *dt)
if err != nil {
return nil, errors.Wrapf(err, "creating nested primitive value %s", selectProp.Name)
}
}
if err != nil {
return nil, errors.Wrapf(err, "serializing field %s", selectProp.Name)
}
}
return x, nil
}
// NewList constructs a ListValue from a general-purpose Go slice.
// The slice elements are converted using NewValue.
func NewPrimitiveList[T bool | float64 | string](v []T, dt schema.DataType) (*pb.ListValue, error) {
var err error
x := &pb.ListValue{Values: make([]*pb.Value, len(v))}
for i, v := range v {
x.Values[i], err = NewPrimitiveValue(v, dt)
if err != nil {
return nil, err
}
}
return x, nil
}
// NewList constructs a ListValue from a general-purpose Go slice.
// The slice elements are converted using NewValue.
func NewObjectList[P schema.PropertyInterface](v []interface{}, parent P, selectProp search.SelectProperty) (*pb.ListValue, error) {
if !selectProp.IsObject {
return nil, errors.New("select property is not an object")
}
x := &pb.ListValue{Values: make([]*pb.Value, len(v))}
for i, v := range v {
if _, ok := v.(map[string]interface{}); !ok {
return nil, protoimpl.X.NewError("invalid type: %T expected map[string]interface{}", v)
}
value, err := NewObject(v.(map[string]interface{}), parent, selectProp)
if err != nil {
return nil, err
}
x.Values[i] = NewObjectValue(value)
}
return x, nil
}
// NewBoolValue constructs a new boolean Value.
func NewBoolValue(v bool) *pb.Value {
return &pb.Value{Kind: &pb.Value_BoolValue{BoolValue: v}}
}
// NewNumberValue constructs a new number Value.
func NewNumberValue(v float64) *pb.Value {
return &pb.Value{Kind: &pb.Value_NumberValue{NumberValue: v}}
}
// NewIntValue constructs a new number Value.
func NewIntValue(v int64) *pb.Value {
return &pb.Value{Kind: &pb.Value_IntValue{IntValue: v}}
}
// NewStringValue constructs a new string Value.
func NewStringValue(v string) *pb.Value {
return &pb.Value{Kind: &pb.Value_StringValue{StringValue: v}}
}
// NewDateValue constructs a new string Value.
func NewDateValue(v string) *pb.Value {
return &pb.Value{Kind: &pb.Value_DateValue{DateValue: v}}
}
// NewUuidValue constructs a new string Value.
func NewUuidValue(v string) *pb.Value {
return &pb.Value{Kind: &pb.Value_UuidValue{UuidValue: v}}
}
// NewGeoValue constructs a new geo Value.
func NewGeoValue(v *models.GeoCoordinates) *pb.Value {
return &pb.Value{Kind: &pb.Value_GeoValue{GeoValue: &pb.GeoCoordinate{Latitude: *v.Latitude, Longitude: *v.Longitude}}}
}
// NewObjectValue constructs a new struct Value.
func NewObjectValue(v *pb.Properties) *pb.Value {
return &pb.Value{Kind: &pb.Value_ObjectValue{ObjectValue: v}}
}
// NewListValue constructs a new list Value.
func NewListValue(v *pb.ListValue) *pb.Value {
return &pb.Value{Kind: &pb.Value_ListValue{ListValue: v}}
}
// NewBlobValue constructs a new blob Value.
func NewBlobValue(v string) *pb.Value {
return &pb.Value{Kind: &pb.Value_BlobValue{BlobValue: v}}
}
// NewPhoneNumberValue constructs a new phone number Value.
func NewPhoneNumberValue(v *models.PhoneNumber) *pb.Value {
return &pb.Value{Kind: &pb.Value_PhoneValue{
PhoneValue: &pb.PhoneNumber{
CountryCode: v.CountryCode,
DefaultCountry: v.DefaultCountry,
Input: v.Input,
InternationalFormatted: v.InternationalFormatted,
National: v.National,
NationalFormatted: v.NationalFormatted,
Valid: v.Valid,
},
}}
}