--- last_review: "2026-05-06" last_reviewer: "s.kaviani" documented_code: [ ] --- ```{tags} advanced-user, tutorial ``` % Issue: https://gitlab.indiscale.com/caosdb/src/linkahead-docs/-/issues/103 # Inserting Records This page covers inserting Records into a LinkAhead instance, referencing other records, and updating property values using PyLinkAhead. | Concept | PyLinkAhead | |-------------------------------------------|------------------------------------------------| | Create a Record | `db.Record()` | | Assign a RecordType to a Record | `.add_parent()` | | Set a property value (with optional unit) | `.add_property(name=..., value=..., unit=...)` | | Retrieve a record from the server | `.retrieve()` | | Update a record | `.update()` | | Fetch a Property by name with server ID | `db.get_entity_by_name()` | ## Prerequisites Make sure you have completed [Creating a Data Model](Data-Insertion.md). The examples on this page assume that the relevant RecordTypes and Properties already exist in the database. ## Inserting a Record `db.Record()` creates an empty record object in Python. You populate it by assigning a parent RecordType and property values, then call `.insert()` to write it to the server: ```{literalinclude} /.assets/tests/tutorials/pylib/test_data_insertion.py :start-after: "# ---- LINK-5 ----" :end-before: "# ---- LINK-6 ----" :language: python :dedent: ``` ```{code-block} text :caption: Output: :class: text-output 256 ``` After insertion the server assigns an integer `id` to the record. The printed value above is an example; the actual id depends on the state of your instance. ## Reference Properties Records can reference other records. If you already know the id of the target record, use it directly as the property value: ```{literalinclude} /.assets/tests/tutorials/pylib/test_data_insertion.py :start-after: "# ---- LINK-6 ----" :end-before: "# ---- LINK-7 ----" :language: python :dedent: ``` Alternatively, pass the Python object itself as the value: ```{literalinclude} /.assets/tests/tutorials/pylib/test_data_insertion.py :start-after: "# ---- LINK-7 ----" :end-before: "# ---- LINK-8 ----" :language: python :dedent: ``` If both records are new, insert them together in a `Container`. The server resolves the reference during insertion: ```{literalinclude} /.assets/tests/tutorials/pylib/test_data_insertion.py :start-after: "# ---- LINK-8 ----" :end-before: "# ---- LINK-9 ----" :language: python :dedent: ``` All three approaches produce an Analysis record that references an Experiment record. ## Named Records and Units Records can have a name and properties can carry units: ```{literalinclude} /.assets/tests/tutorials/pylib/test_data_insertion.py :start-after: "# ---- LINK-10 ----" :end-before: "# ---- LINK-11 ----" :language: python :dedent: ``` ```{code-block} text :caption: Output: :class: text-output DeviceNo-AB110 301 ``` The name is preserved after insertion and the server assigns an id. ## Batch Insertion To insert many records at once, build a `Container` in a loop and call `.insert()` once at the end: ```{literalinclude} /.assets/tests/tutorials/pylib/test_data_insertion.py :start-after: "# ---- LINK-12 ----" :end-before: "# ---- LINK-13 ----" :language: python :dedent: ``` ```{code-block} text :caption: Output: :class: text-output 3 ``` ## Working with List Values Use `.retrieve()` to fetch the current state of a record from the server by name or id. The following example inserts a record with an initial list value, retrieves it, extends the list, and persists the change with `.update()`: ```{literalinclude} /.assets/tests/tutorials/pylib/test_data_insertion.py :start-after: "# ---- LINK-16 ----" :end-before: "# ---- LINK-17 ----" :language: python :dedent: ``` ```{code-block} text :caption: Output: :class: text-output [1, 2, 3, 4, 5] ``` `.retrieve()` is necessary before modifying because `.update()` sends the entire local object state back to the server. Modifying a record without retrieving first would overwrite the server's current value rather than extending it. ## Updating Records When you update a record, any property you add must already have an id. Adding a property by name alone will fail: ```{literalinclude} /.assets/tests/tutorials/pylib/test_data_insertion.py :start-after: "# ---- LINK-18 ----" :end-before: "# ---- LINK-19 ----" :language: python :dedent: ``` ```{code-block} text :caption: Output: :class: text-output TransactionError: PROPERTY (id: None, name: 'date') CAUSED EntityError: Entity has no ID. ``` Use `get_entity_by_name()` to fetch the Property entity with its id before adding it: ```{literalinclude} /.assets/tests/tutorials/pylib/test_data_insertion.py :start-after: "# ---- LINK-20 ----" :end-before: "# ---- LINK-21 ----" :language: python :dedent: ``` Additional information about record retrieval and caching for performance-sensitive code can be found in the [Features of Interest](/explanation/pylib/features_of_interest.md) document. For updating uploaded files, see [How to Update a File](/how_to/dev_guides/pylib/update_file.md). ## Summary This tutorial covered inserting Records, using reference properties, batch insertion, working with list values, and updating records correctly. Continue with [Scripting with LinkAhead](python_script.md) for a demonstration on how to build a script to automatically update data in linkahead.