Tagging data#
Add tags to the points you upload or stream, so one dataset can hold data from many units or executions and still be filtered by each. Tags are the basis of the tagged approach.
In code#
When you upload a file:
from nominal.core import NominalClient
client = NominalClient.from_profile("default")
dataset = client.get_dataset("<ri.catalog.instance.dataset.identifier>")
file = dataset.add_tabular_data(
"sample.csv",
timestamp_column="timestamp",
timestamp_type="iso_8601",
tags={"UUT": "A"}, # the same tag on every row
# or tag_columns={"UUT": "unit"} to take each row's tag from the file's unit column
)
file.poll_until_ingestion_completed() # raises NominalIngestError if the ingest fails
client = nominal.Client.fromProfile();
dataset = client.datasetByRid("<ri.catalog.instance.dataset.identifier>");
% The same tag on every row
client.ingest("sample.csv", TimestampColumn="timestamp", Dataset=dataset, Tags=struct(UUT="A"));
use nominal::core::{CsvIngest, Timestamp};
let client = nominal::NominalClient::from_profile("default")?;
let csv = CsvIngest::new(Timestamp::iso8601("timestamp"))
.additional_file_tag("UUT", "A"); // the same tag on every row
// or .tag_column("UUT", "unit") to take each row's tag from the file's unit column
client.ingest().upload_csv("sample.csv", "<ri.catalog.instance.dataset.identifier>", csv).await?;
import (
"bytes"
"os"
ingestapi "github.com/nominal-io/nominal-api-go/ingest/api"
nominalapi "github.com/nominal-io/nominal-api-go/io/nominal/api"
uploadapi "github.com/nominal-io/nominal-api-go/upload/api"
"github.com/palantir/conjure-go-runtime/v2/conjure-go-client/httpclient"
"github.com/palantir/pkg/rid"
"github.com/palantir/pkg/safelong"
)
// httpClient is a conjure-go-runtime httpclient.Client for your Nominal REST API URL,
// and token is your API key as a bearertoken.Token
data, _ := os.ReadFile("sample.csv")
size := safelong.SafeLong(len(data))
path, _ := uploadapi.NewUploadServiceClient(httpClient).UploadFile(ctx, token, "sample.csv", &size, nil,
httpclient.RequestBodyInMemory(bytes.NewReader(data)))
datasetRid, _ := rid.ParseRID("<ri.catalog.instance.dataset.identifier>")
tags := map[nominalapi.TagName]nominalapi.TagValue{"UUT": "A"} // the same tag on every row
ingestapi.NewIngestServiceClient(httpClient).Ingest(ctx, token, ingestapi.IngestRequest{
Options: ingestapi.NewIngestOptionsFromCsv(ingestapi.CsvOpts{
Source: ingestapi.NewIngestSourceFromS3(ingestapi.S3IngestSource{Path: string(path)}),
Target: ingestapi.NewDatasetIngestTargetFromExisting(ingestapi.ExistingDatasetIngestDestination{DatasetRid: datasetRid}),
TimestampMetadata: ingestapi.TimestampMetadata{
SeriesName: "timestamp",
TimestampType: ingestapi.NewTimestampTypeFromAbsolute(ingestapi.NewAbsoluteTimestampFromIso8601(ingestapi.Iso8601Timestamp{})),
},
AdditionalFileTags: &tags,
// or TagColumns to take each row's tag from a column of the file
}),
})
When you stream points:
from datetime import datetime, timezone
from nominal.core import NominalClient
client = NominalClient.from_profile("default")
dataset = client.get_dataset("<ri.catalog.instance.dataset.identifier>")
with dataset.get_write_stream() as stream:
stream.enqueue("temperature", datetime.now(timezone.utc), 25.0, tags={"UUT": "A"})
client = nominal.Client.fromProfile();
dataset = client.datasetByRid("<ri.catalog.instance.dataset.identifier>");
stream = dataset.stream();
temperature = stream.channel("temperature");
temperature.tag("UUT", "A"); % applies to every point pushed after it
temperature.push(datetime("now", TimeZone="UTC"), 25.0);
use nominal::streaming::prelude::*;
use nominal::streaming::stream::NominalDatasetStreamBuilder;
use std::time::UNIX_EPOCH;
// token: your API key, as a BearerToken
let stream = NominalDatasetStreamBuilder::new()
.stream_to_core(token, ResourceIdentifier::new("<ri.catalog.instance.dataset.identifier>")?, tokio::runtime::Handle::current())
.build();
stream
.double_writer(ChannelDescriptor::with_tags("temperature", [("UUT", "A")]))
.push(UNIX_EPOCH.elapsed()?, 25.0);
import (
"time"
nominal "github.com/nominal-io/nominal-streaming-go"
)
// apiKey is your API key
streamClient, _ := nominal.NewClient(apiKey)
stream, _, _ := streamClient.NewDatasetStream(ctx, "<ri.catalog.instance.dataset.identifier>")
stream.FloatStream("temperature", nominal.WithTags(nominal.Tags{"UUT": "A"})).Enqueue(time.Now().UnixNano(), 25.0)
stream.Close()
In the Nominal app#
In the upload wizard’s Settings panel:
To give every row the same tag, under Tags click ADD TAG, choose or create the tag key, then click its value and choose or create the value.
To take each row’s tag from a column of the file, under Tag columns click ADD TAG COLUMN and pick the column. The column’s name becomes the tag key, and you can rename it. Tag columns work for CSV and Parquet files.
Streamed points get their tags from the code that streams them.