Skip to content

Commit

Permalink
[FSTORE-332] implement method for get_or_create_feature_view (logical…
Browse files Browse the repository at this point in the history
…clocks#813)

* get_or_create_feature_view
  • Loading branch information
davitbzh authored and kennethmhc committed Nov 16, 2022
1 parent ea37a3b commit 21b9418
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 22 deletions.
39 changes: 35 additions & 4 deletions java/src/main/java/com/logicalclocks/hsfs/FeatureStore.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package com.logicalclocks.hsfs;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.logicalclocks.hsfs.constructor.Query;
import com.logicalclocks.hsfs.engine.FeatureViewEngine;
import com.logicalclocks.hsfs.engine.SparkEngine;
import com.logicalclocks.hsfs.metadata.FeatureGroupApi;
Expand Down Expand Up @@ -253,14 +254,14 @@ public FeatureGroup.FeatureGroupBuilder createFeatureGroup() {
}

public FeatureGroup getOrCreateFeatureGroup(String name, Integer version) throws IOException, FeatureStoreException {
return featureGroupApi.getOrCreateFeatureGroup(this, name, version, null, null,
return featureGroupApi.getOrCreateFeatureGroup(this, name, version, null, null,
null, null, false, null, null, null);
}

public FeatureGroup getOrCreateFeatureGroup(String name, Integer version, List<String> primaryKeys,
boolean onlineEnabled, String eventTime)
throws IOException, FeatureStoreException {
return featureGroupApi.getOrCreateFeatureGroup(this, name, version, null, primaryKeys,
return featureGroupApi.getOrCreateFeatureGroup(this, name, version, null, primaryKeys,
null, null, onlineEnabled, null, null, eventTime);
}

Expand All @@ -270,7 +271,7 @@ public FeatureGroup getOrCreateFeatureGroup(String name, Integer version,
boolean onlineEnabled,
String eventTime) throws IOException, FeatureStoreException {

return featureGroupApi.getOrCreateFeatureGroup(this, name, version, null, primaryKeys,
return featureGroupApi.getOrCreateFeatureGroup(this, name, version, null, primaryKeys,
partitionKeys, null, onlineEnabled, null, null, eventTime);
}

Expand All @@ -281,7 +282,7 @@ public FeatureGroup getOrCreateFeatureGroup(String name, Integer version, String
StatisticsConfig statisticsConfig, String eventTime)
throws IOException, FeatureStoreException {

return featureGroupApi.getOrCreateFeatureGroup(this, name, version, description, primaryKeys,
return featureGroupApi.getOrCreateFeatureGroup(this, name, version, description, primaryKeys,
partitionKeys, hudiPrecombineKey, onlineEnabled, timeTravelFormat, statisticsConfig, eventTime);
}

Expand Down Expand Up @@ -338,6 +339,36 @@ public FeatureView.FeatureViewBuilder createFeatureView() {
return new FeatureView.FeatureViewBuilder(this);
}

/**
* Get feature view metadata object or create a new one if it doesn't exist. This method doesn't update
* existing feature view metadata object.
*
* @param name name of the feature view
* @param query Query object
* @param version version of the feature view
* @return FeatureView
*/
public FeatureView getOrCreateFeatureView(String name, Query query, Integer version)
throws FeatureStoreException, IOException {
return featureViewEngine.getOrCreateFeatureView(this, name, version, query, null, null);
}

/**
* Get feature view metadata object or create a new one if it doesn't exist. This method doesn't update
* existing feature view metadata object.
*
* @param name name of the feature view
* @param query Query object
* @param version version of the feature view
* @param description description of the feature view
* @param labels list of label features
* @return FeatureView
*/
public FeatureView getOrCreateFeatureView(String name, Query query, Integer version, String description,
List<String> labels) throws FeatureStoreException, IOException {
return featureViewEngine.getOrCreateFeatureView(this, name, version, query, description, labels);
}

/**
* Get a feature view object from the selected feature store.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -411,4 +411,24 @@ public Map<String, Object> getTags(FeatureView featureView, Integer trainingData
throws FeatureStoreException, IOException {
return tagsApi.get(featureView, trainingDataVersion);
}

public FeatureView getOrCreateFeatureView(FeatureStore featureStore, String name, Integer version, Query query,
String description, List<String> labels)
throws FeatureStoreException, IOException {
FeatureView featureView = null;
try {
featureView = get(featureStore, name, version);
} catch (IOException | FeatureStoreException e) {
if (e.getMessage().contains("Error: 404") && e.getMessage().contains("\"errorCode\":270181")) {
featureView = new FeatureView.FeatureViewBuilder(featureStore)
.name(name)
.version(version)
.query(query)
.description(description)
.labels(labels)
.build();
}
}
return featureView;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ public <S> void insert(StreamFeatureGroup streamFeatureGroup, S featureData,
public <S> StreamFeatureGroup saveFeatureGroupMetaData(StreamFeatureGroup featureGroup, List<String> partitionKeys,
String hudiPrecombineKey, Map<String, String> writeOptions,
JobConfiguration sparkJobConfiguration, S featureData)
throws FeatureStoreException, IOException, ParseException {
throws FeatureStoreException, IOException {

if (featureGroup.getFeatures() == null) {
featureGroup.setFeatures(utils
Expand Down
50 changes: 50 additions & 0 deletions python/hsfs/feature_store.py
Original file line number Diff line number Diff line change
Expand Up @@ -967,6 +967,56 @@ def create_feature_view(
)
return self._feature_view_engine.save(feat_view)

def get_or_create_feature_view(
self,
name: str,
query: Query,
version: int,
description: Optional[str] = "",
labels: Optional[List[str]] = [],
transformation_functions: Optional[Dict[str, TransformationFunction]] = {},
):
"""Get feature view metadata object or create a new one if it doesn't exist. This method doesn't update
existing feature view metadata object.
# Arguments
name: Name of the feature view to create.
query: Feature store `Query`.
version: Version of the feature view to create.
description: A string describing the contents of the feature view to
improve discoverability for Data Scientists, defaults to empty string
`""`.
labels: A list of feature names constituting the prediction label/feature of
the feature view. When replaying a `Query` during model inference,
the label features can be omitted from the feature vector retrieval.
Defaults to `[]`, no label.
transformation_functions: A dictionary mapping tansformation functions to
to the features they should be applied to before writing out the
vector and at inference time. Defaults to `{}`, no
transformations.
# Returns:
`FeatureView`: The feature view metadata object.
"""

try:
return self._feature_view_engine.get(name, version)
except exceptions.RestAPIError as e:
if (
e.response.json().get("errorCode", "") == 270181
and e.response.status_code == 404
):
return self.create_feature_view(
name=name,
query=query,
version=version,
description=description,
labels=labels,
transformation_functions=transformation_functions,
)
else:
raise e

def get_feature_view(self, name: str, version: int = None):
"""Get a feature view entity from the feature store.
Expand Down
32 changes: 15 additions & 17 deletions python/tests/fixtures/generate_backend_fixtures.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -354,17 +354,12 @@
" fg_2.save(df_2)\n",
" \n",
" # fv\n",
"\n",
" try:\n",
" self.feature_view = fs.get_feature_view('fv_test')\n",
" except RestAPIError:\n",
" query = fg_1.select_all().join(fg_2.select_all())\n",
" \n",
" self.feature_view = fs.create_feature_view(\n",
" name='fv_test',\n",
" query=query,\n",
" version=1\n",
" )\n",
" query = fg_1.select_all().join(fg_2.select_all())\n",
" self.feature_view = fs.get_or_create_feature_view(\n",
" name='fv_test',\n",
" query=query,\n",
" version=1\n",
" )\n",
"\n",
" def call(self):\n",
" fs.get_feature_view('fv_test')\n",
Expand Down Expand Up @@ -559,20 +554,23 @@
],
"metadata": {
"kernelspec": {
"display_name": "PySpark",
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "pysparkkernel"
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "python",
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "pyspark",
"pygments_lexer": "python3"
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.8"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
}

0 comments on commit 21b9418

Please sign in to comment.