@@ -10,6 +10,8 @@ import (
1010 timestamppb "google.golang.org/protobuf/types/known/timestamppb"
1111 "io/ioutil"
1212 "strings"
13+ "sort"
14+ "fmt"
1315)
1416
1517type FeatureStore struct {
@@ -62,52 +64,13 @@ func (fs *FeatureStore) GetOnlineFeatures(request *serving.GetOnlineFeaturesRequ
6264 }
6365
6466 requestEntities := request .GetEntities () // map[string]*types.RepeatedValue
65- registryEntities := fs .registry .GetEntities () //[]*Entity
66- entitiesInRegistry := make (map [string ]bool ) // used for validation of requested entities versus registry entities
67- var requestEntitiesRowLength int
68-
69- for _ , values := range requestEntities {
70- requestEntitiesRowLength = len (values .GetVal ())
71- break
72- }
73- for _ , registryEntity := range registryEntities {
74- // append(entities_in_registry, registry_entity.Spec.Name)
75- entitiesInRegistry [registryEntity .Spec .Name ] = true
76- }
77- joinKeyIndex := 0
78- joinKeyToIndex := make (map [string ]int )
79- // Validate that all entities in request_entities are found in registry
80- for entityName , values := range requestEntities {
81- if _ , ok := entitiesInRegistry [entityName ]; ! ok {
82- return nil , errors .New ("Requested entity not found inside the registry" )
83- }
84- if len (values .GetVal ()) != requestEntitiesRowLength {
85- return nil , errors .New ("Values of each Entity must have the same length" )
86- }
87- joinKeyToIndex [entityName ] = joinKeyIndex
88- joinKeyIndex += 1
89- }
67+
9068 // Construct a map of all feature_views to validate later
9169 registryFeatureViews := fs .registry .GetFeatureViews ()
9270 featureViewsInRegistry := make (map [string ]* core.FeatureView )
9371 for _ , registryFeatureView := range registryFeatureViews {
9472 featureViewsInRegistry [registryFeatureView .Spec .Name ] = registryFeatureView
9573 }
96- numRequestJoinKeys := len (requestEntities )
97- entityKeys := make ([]types.EntityKey , requestEntitiesRowLength )
98- for index , _ := range entityKeys {
99- entityKey := types.EntityKey { JoinKeys : make ([]string , numRequestJoinKeys ),
100- EntityValues : make ([]* types.Value , numRequestJoinKeys )}
101- entityKeys [index ] = entityKey
102- }
103- // Building entity keys
104- for joinKey , values := range requestEntities {
105- for rowEntityKeyIndex , value := range values .GetVal () {
106- joinKeyIndex := joinKeyToIndex [joinKey ]
107- entityKeys [rowEntityKeyIndex ].JoinKeys [joinKeyIndex ] = joinKey
108- entityKeys [rowEntityKeyIndex ].EntityValues [joinKeyIndex ] = value
109- }
110- }
11174
11275 response := serving.GetOnlineFeaturesResponse {Metadata : & serving.GetOnlineFeaturesResponseMetadata {FeatureNames : featureList },
11376 Results : make ([]* serving.GetOnlineFeaturesResponse_FeatureVector , 0 )}
@@ -123,12 +86,55 @@ func (fs *FeatureStore) GetOnlineFeatures(request *serving.GetOnlineFeaturesRequ
12386 // Obtain all join keys required by this feature view
12487 // and for each join key, create a EntityKey
12588 // and add to entity_keys
126- entitiesRequired := featureViewSpec .GetEntities ()
127- for _ , entityName := range entitiesRequired {
128- if _ , ok := requestEntities [entityName ]; ! ok {
129- return nil , errors .New ("All entities inside FeatureView must be provided" )
89+ entitiesInFeatureView := featureViewSpec .GetEntities ()
90+ sort .Strings (entitiesInFeatureView )
91+ featuresInFeatureView := featureViewSpec .GetFeatures ()
92+ // Validate that all features asked for are inside this feature view
93+ featuresInFeatureViewMap := make (map [string ]bool )
94+ for _ , featureRef := range featuresInFeatureView {
95+ featuresInFeatureViewMap [featureRef .GetName ()] = true
96+ }
97+
98+ for _ , featureName := range allFeatures {
99+ if _ , ok := featuresInFeatureViewMap [featureName ]; ! ok {
100+ return nil , errors .New (fmt .Sprintf ("FeatureView: %s doesn't contain feature: %s\n " , featureViewName , featureName ))
130101 }
131102 }
103+
104+ var entityKeys []types.EntityKey
105+ // Construct EntityKeys
106+ if len (entitiesInFeatureView ) > 0 {
107+
108+ if _ , ok := requestEntities [entitiesInFeatureView [0 ]]; ! ok {
109+ return nil , errors .New (fmt .Sprintf ("EntityKey: %s is required for feature view: %s\n " , entitiesInFeatureView [0 ], featureViewName ))
110+ }
111+ requestEntitiesRowLength := len (requestEntities [entitiesInFeatureView [0 ]].GetVal ())
112+
113+ numJoinKeysInFeatureView := len (entitiesInFeatureView )
114+ entityKeys = make ([]types.EntityKey , requestEntitiesRowLength )
115+ for index , _ := range entityKeys {
116+ entityKey := types.EntityKey { JoinKeys : make ([]string , numJoinKeysInFeatureView ),
117+ EntityValues : make ([]* types.Value , numJoinKeysInFeatureView )}
118+ entityKeys [index ] = entityKey
119+ }
120+ // Building entity keys for required for each Feature View from the Feature View's Spec
121+ for joinKeyIndex , joinKey := range entitiesInFeatureView {
122+ if values , ok := requestEntities [joinKey ]; ! ok {
123+ return nil , errors .New (fmt .Sprintf ("EntityKey: %s is required for feature view: %s\n " , joinKey , featureViewName ))
124+ } else {
125+ // All requested entities must have the same number of rows
126+ if len (values .GetVal ()) != requestEntitiesRowLength {
127+ return nil , errors .New ("Values of each Entity must have the same length" )
128+ }
129+ for rowEntityKeyIndex , value := range values .GetVal () {
130+ entityKeys [rowEntityKeyIndex ].JoinKeys [joinKeyIndex ] = joinKey
131+ entityKeys [rowEntityKeyIndex ].EntityValues [joinKeyIndex ] = value
132+ }
133+ }
134+ }
135+
136+ }
137+
132138
133139 features , err := fs .onlineStore .OnlineRead (entityKeys , featureViewName , allFeatures )
134140
@@ -149,7 +155,6 @@ func (fs *FeatureStore) GetOnlineFeatures(request *serving.GetOnlineFeaturesRequ
149155 } else if checkOutsideMaxAge (& feature .timestamp , timestamppb .Now (), featureViewSpec .GetTtl ()) {
150156 status = serving .FieldStatus_OUTSIDE_MAX_AGE
151157 }
152-
153158 value := feature .value
154159 timeStamp := feature .timestamp
155160 featureVector .Values = append (featureVector .Values , & value )
0 commit comments