## lamindb.Record

| class lamindb.Record(name: str | None = None, type: Record | None = None, is_type: bool = False, features: dict[str | Feature, Any] | None = None, description: str | None = None, schema: Schema | None = None, reference: str | None = None, reference_type: str | None = None, branch: Branch | None = None, space: Space | None = None) |
class lamindb.Record(*db_args)

 Bases: "SQLRecord", "HasType", "HasParents", "CanCurate",
 "TracksRun", "TracksUpdates"

 Flexible records with markdown notes, dynamic registries, and
 sheets.

 Useful for managing notes, experiments, samples, donors, cells,
 compounds, sequences, and other custom entities with their
 features.

 Parameters:
| * **name** -- "str | None = None" A name. |

| * **description** -- "str | None = None" A description. |

| * **type** -- "Record | None = None" The type of this record. |

 * **is_type** -- "bool = False" Whether this record is a type (a
 record that classifies other records).

| * **features** -- "dict[str | Feature, Any] | None = None" Lazy |
 feature values to persist on ".save()" or "ln.save([...])".

| * **schema** -- "Schema | None = None" A schema defining allowed |
 features for records of this type. Only applicable when
 "is_type=True".

| * **reference** -- "str | None = None" For instance, an external |
 ID or a URL.

| * **reference_type** -- "str | None = None" For instance, |
 ""url"".

| * **branch** -- "Branch | None = None" A branch. If "None", uses |
 the current branch.

| * **space** -- "Space | None = None" A space. If "None", uses |
 the current space.

 See also:

 "Feature"
 Measurable properties such as columns of a sheet.

 "Schema"
 Constrain sheet columns; "index" defines row keys.

 "ULabel"
 Simple universal labels.

# Examples

 Create a **record** with a single feature:

 # create a feature if you don't yet have one
 gc_content = ln.Feature(name="gc_content", dtype=float).save()

 # create a record to track a sample
 sample1 = ln.Record(name="Sample 1", features={"gc_content": 0.5}).save()

 # describe the record
 sample1.describe()

 Group records in a dynamic registry by creating a **record type**,
 optionally constrained with a "Schema":

 # create an experiments registry
 experiments_registry = ln.Record(name="Experiments", is_type=True).save()
 experiment1 = ln.Record(name="Experiment 1", type=experiments_registry).save()

 # create a feature to link experiments
 experiment = ln.Feature(name="experiment", dtype=experiments_registry).save()

 # constrain a samples registry with a schema, turning it into a sheet
 schema = ln.Schema([experiment, gc_content.with_config(optional=True)], name="sample_schema").save()
 sample_sheet = ln.Record(name="Sample Sheet", is_type=True, schema=schema).save()

 # move the sample1 record into the sample sheet
 sample1.type = sample_sheet
 sample1.save()

 # reset the feature values for the record including the experiment
 sample1.features.set_values({
 gc_content: 0.5,
 experiment: "Experiment 1",  # automatically resolves by name, also accepts the experiment1 object
 })

 Export all records of a type to a dataframe:

 experiments_registry.to_dataframe()
 #> __lamindb_record_name__ ...
 #> Experiment 1 ...
 #> Experiment 2 ...

 Use "index" on a sheet schema to define row keys:

 sample_id = ln.Feature(name="sample_id", dtype=str).save()
 score = ln.Feature(name="score", dtype=float).save()
 schema = ln.Schema(features=[score], index=sample_id).save()
 sheet = ln.Record(name="Samples", is_type=True, schema=schema).save()

 record = ln.Record(type=sheet, features={"sample_id": "S-001", "score": 1.5}).save()
 assert record.name == "S-001"

 df = sheet.to_dataframe()
 assert df.index.name == "sample_id"
 assert "sample_id" not in df.columns

 Import records from a dataframe "from_dataframe()":

 records = ln.Record.from_dataframe(df, type="my_df").save()  # creates a type my_df with inferred schema

 If you try to set incomplete features in a record in a sheet,
 you'll get a validation error:

 sample2 = ln.Record(name="Sample 2", type=sample_sheet).save()
 sample2.features.set_values({gc_content: 0.6})  # raises ValidationError because experiment is missing

 Query records by features:

 ln.Record.filter(gc_content == 0.55)  # exact match
 ln.Record.filter(gc_content > 0.5) # greater than

 Query records by field:

 ln.Record.filter(type=sample_sheet) # just the record on the sheet

# Notes

 **Schema index.** When a sheet schema defines "index", the index
 feature acts as the row key — analogous to "df.index" for tabular
 data. The index feature must have "dtype=str" because values are
 stored on "name":

 * **Write**: "Record(features=...)", "features.add_values()", and
 "from_dataframe()" route the index feature to "name" and do not
 write it to link tables.

 * **Read**: "features.get_values()" injects the index from
 "Record.name".

 * **Export**: "to_dataframe()" puts the index on "df.index" (named
 after the index feature) and omits encoded metadata columns
 ("__lamindb_record_id__", "__lamindb_record_uid__",
 "__lamindb_record_name__", etc.). Sheets without "index" keep the
 previous export behavior.

 * **Import**: "from_dataframe()" accepts a dataframe whose index
 matches the schema index feature (or the index feature as a
 column).

 * **CSV**: "to_artifact()" writes with "index=True" when an index
 is configured.

 You can edit records like spreadsheets on the hub:

 [image]

 Just like for "ULabel", you can also model **ontologies** through
 the "parents"/"children" attributes.

 -[ What is the difference between "Record" and "SQLRecord"? ]-

 The features of a "Record" are flexible: you can dynamically define
 features and add features to a record. The fields of a "SQLRecord"
 are static: you need to define them in code and then migrate the
 underlying database.

 In complete analogy to this: A **record type** can model a registry
 dynamically, whereas a "Registry" has to be defined as a static
 Python class together with its SQL database migration:  "lamin
 migrate create" and "lamin migrate deploy".

 See "SQLRecord" or the glossary for more information: record.

 property features: FeatureManager

 Manage the linked feature values.

 For examples, see "Record".

 property is_sheet: bool

 Check if record is a "sheet", i.e., "self.is_type and
 self.schema is not None".

 uid: "str"

 A universal random id, valid across DB instances.

 name: "str"

 Name or title of record (optional).

| description: "str" | "None" |

 A description.

| reference: "str" | "None" |

 A simple reference like a URL or external ID.

| reference_type: "str" | "None" |

 Type of simple reference.

| extra_data: "dict" | "None" |

 Extra data in JSON format, not validated as features.

| type: Record | None |

 Type of record, e.g., "Sample", "Donor", "Cell", "Compound",
 "Sequence" ← "records".

 Allows to group records by type, e.g., all samples, all donors,
 all cells, all compounds, all sequences.

| schema: Schema | None |

 A schema to enforce for a type ← "records".

 This is analogous to the "schema" attribute of an "Artifact". If
 "is_type" is "True", the schema is used to enforce features for
 each record of this type.

 parents: RelatedManager[Record]

 Ontological parents of this record ← "children".

 You can build an ontology under a given "type". For example,
 introduce a type "CellType" and model the hiearchy of cell types
 under it via "parents" and "children".

 input_of_runs: RelatedManager[Run]

 Runs that use this record as an input ← "input_records".

 artifacts: RelatedManager[Artifact]

 Artifacts annotated by this record ← "records".

 runs: RelatedManager[Run]

 Runs annotated by this record ← "records".

 transforms: RelatedManager[Transform]

 Transforms annotated by this record ← "records".

 collections: RelatedManager[Collection]

 Collections annotated by this record ← "records".

 records: RelatedManager[Record]

 If a "type" ("is_type=True"), records of this "type".

 children: RelatedManager[Record]

 Ontological children of this record. Is reverse accessor for
 "parents".

 references: RelatedManager[Reference]

 References that annotate this record ← "records".

 projects: RelatedManager[Project]

 Projects that annotate this record ← "records".

 ablocks: RelatedManager[RecordBlock]

 Attached blocks ← "record".

 linked_records: RelatedManager[Record]

 Records linked in this record as a value ← "linked_in_records".

 linked_users: RelatedManager[User]

 Users linked in this record as values ← "linked_in_records".

 linked_runs: RelatedManager[Run]

 Runs linked in this record as values ← "linked_in_records".

 linked_transforms: RelatedManager[Transform]

 Transforms linked in this record as values ←
 "linked_in_records".

 linked_ulabels: RelatedManager[ULabel]

 ULabels linked in this record as values ← "linked_in_records".

 linked_artifacts: RelatedManager[Artifact]

 Artifacts linked in this record as values ← "linked_in_records".

 linked_collections: RelatedManager[Collection]

 Collections linked in this record as values ←
 "linked_in_records".

 linked_in_records: RelatedManager[Record]

 Records linking this record as a value. Is reverse accessor for
 "linked_records".

 linked_references: RelatedManager[Reference]

 References linked in this record as values ←
 "linked_in_records".

 linked_projects: RelatedManager[Project]

 Projects linked in this record as values ← "linked_in_records".

 values_json: RelatedManager[RecordJson]

 JSON values "(record_id, feature_id, value)".

 values_record: RelatedManager[RecordRecord]

 Record values with their features "(record_id, feature_id,
 value_id)".

 values_ulabel: RelatedManager[RecordULabel]

 ULabel values with their features "(record_id, feature_id,
 value_id)".

 values_user: RelatedManager[RecordUser]

 User values with their features "(record_id, feature_id,
 value_id)".

 values_run: RelatedManager[RecordRun]

 Run values with their features "(record_id, feature_id,
 value_id)".

 values_artifact: RelatedManager[RecordArtifact]

 Artifact values with their features "(record_id, feature_id,
 value_id)".

 values_collection: RelatedManager[RecordCollection]

 Collection values with their features "(record_id, feature_id,
 value_id)".

 values_transform: RelatedManager[RecordTransform]

 Transform values with their features "(record_id, feature_id,
 value_id)".

 values_reference: RelatedManager[RecordReference]

 Reference values with their features "(record_id, feature_id,
 value_id)".

 values_project: RelatedManager[RecordProject]

 Project values with their features "(record_id, feature_id,
 value_id)".

 from_dataframe(*, type, name_field='__lamindb_record_name__')

 Construct a dataframe-backed batch of records for bulk saving.

 Returns a "RecordBatch". Follow with "records.save()".

 When the target sheet schema defines "index", the index feature
 may be passed on "df.index" (named after the feature) or as a
 column.

 Parameters:
 * **df** ("DataFrame") -- A dataframe where rows represent
 records.

| * **type** ("Record" | "str") -- Record type for all rows as |
 either a "Record" object or a string. If passing a string,
 a new type with that name is created under "Imports" with
 an inferred schema from the dataframe. If that type name
 already exists, raise an error and pass an existing
 "Record" object for reuse. If the resolved type is a sheet
 ("type.schema is not None"), feature values are validated
 against that schema at save time.

 * **name_field** ("str", default:
 "'__lamindb_record_name__'") -- Column used for record
 names when no schema index is configured. Falls back to
 "name" if absent. If neither exists, records are created
 without names.

 Return type:
 "RecordBatch"

 -[ Examples ]-

 Create a new type and import records:

 records = ln.Record.from_dataframe(df, type="my_df").save()

 Import records into an existing type:

 records = ln.Record.from_dataframe(df, type=sample_sheet).save()

 save(*args, **kwargs)

 Return type:
 "Record"

 query_parents()

 Query all parents of a record recursively.

 While ".parents" retrieves the direct parents, this method
 retrieves all ancestors of the current record.

 Return type:
 "QuerySet"

 query_children()

 Query all children of a record recursively.

 While ".children" retrieves the direct children, this method
 retrieves all descendants of a parent.

 Return type:
 "QuerySet"

 query_records()

 Query records of sub types.

 While ".records" retrieves the records with the current type,
 this method also retrieves sub types and the records with sub
 types of the current type.

 Return type:
 "QuerySet"

 to_dataframe(is_run_input=None, link_individual_inputs=True, use_export_run=False, **kwargs)

 Evaluate and convert to "pd.DataFrame".

 By default, this returns up to 20 rows for a fast overview. Pass
 "limit=None" to fetch all matching records.

 By default, maps simple fields and foreign keys onto "DataFrame"
 columns.

 Guide: Query & search

 Parameters:
 * **include** -- Related data to include as columns. Takes
 strings of form ""records__name"", ""cell_types__name"",
 etc. or a list of such strings. For "Artifact", "Record",
 and "Run", can also pass ""features"" to include features
 measured in the current queryset. If ""privates"", includes
 private fields (fields starting with "_").

 * **features** -- Configure the features to include. Can be a
 feature name or a list of such names. Only available for
 "Artifact", "Record", and "Run".

 * **limit** -- Maximum number of rows to display. Defaults to
 20. If "None", includes all results.

 * **order_by** -- Field name to order the records by. Prefix
 with '-' for descending order. Defaults to '-id' to get the
 most recent records. This argument is ignored if the
 queryset is already ordered or if the specified field does
 not exist.

 Return type:
 "DataFrame"

 -[ Examples ]-

 Include the name of the creator:

 ln.Record.to_dataframe(include="created_by__name"])

 Include features:

 ln.Artifact.to_dataframe(include="features")

 Include selected features:

 ln.Artifact.to_dataframe(features=["cell_type_by_expert", "cell_type_by_model"])

 to_artifact(key=None, suffix=None, is_run_input=None, link_individual_inputs=True, **kwargs)

 Calls "to_dataframe()" to create an artifact.

 The format defaults to ".csv" unless "suffix" is passed or "key"
 specifies another format.

 The "key" defaults to "sheet_exports/{self.name}{suffix}" unless
 a "key" is passed.

 When the sheet schema defines "index", the CSV is written with
 "index=True" so the index feature is preserved on export.

 -[ Example ]-

 Export all records on a sheet to an artifact:

 sample_sheet.to_artifact()

 Parameters:
| * **key** ("str" | "None", default: "None") -- The artifact |
 key.

| * **suffix** ("str" | "None", default: "None") -- The suffix |
 to append to the default key if no key is passed.

| * **is_run_input** ("bool" | "Run" | "None", default: "None") |
 -- Whether to track the record as a run input.

 * **link_individual_inputs** ("bool", default: "True") --
 Whether to link all exported records as inputs of the
 export run. If "False", only links the record type.

 * ****kwargs** -- Keyword arguments passed to
 "to_dataframe()".

 Return type:
 "Artifact"