Insert
Insert operations add new data to Fluree. This is the most common transaction type for creating new entities and relationships.
Basic Insert
Single Entity
Insert a single entity with properties:
curl -X POST "http://localhost:8090/v1/fluree/insert?ledger=mydb:main" \
-H "Content-Type: application/json" \
-d '{
"@context": {
"ex": "http://example.org/ns/",
"schema": "http://schema.org/"
},
"@graph": [
{
"@id": "ex:alice",
"@type": "schema:Person",
"schema:name": "Alice",
"schema:email": "alice@example.org",
"schema:age": 30
}
]
}'
Result:
{
"t": 1,
"timestamp": "2024-01-22T10:30:00.000Z",
"commit_id": "bafybeig...commitT1",
"flakes_added": 4,
"flakes_retracted": 0
}
This creates 4 triples:
ex:alice rdf:type schema:Person
ex:alice schema:name "Alice"
ex:alice schema:email "alice@example.org"
ex:alice schema:age 30
Multiple Entities
Insert multiple entities in one transaction:
{
"@context": {
"ex": "http://example.org/ns/",
"schema": "http://schema.org/"
},
"@graph": [
{
"@id": "ex:alice",
"@type": "schema:Person",
"schema:name": "Alice"
},
{
"@id": "ex:bob",
"@type": "schema:Person",
"schema:name": "Bob"
},
{
"@id": "ex:carol",
"@type": "schema:Person",
"schema:name": "Carol"
}
]
}
Benefits:
- Atomic: All entities created or none
- Efficient: Single commit, single index update
- Consistent: All entities at same transaction time
Insert with Relationships
Create entities with relationships:
{
"@context": {
"ex": "http://example.org/ns/",
"schema": "http://schema.org/"
},
"@graph": [
{
"@id": "ex:company-a",
"@type": "schema:Organization",
"schema:name": "Acme Corp"
},
{
"@id": "ex:alice",
"@type": "schema:Person",
"schema:name": "Alice",
"schema:worksFor": { "@id": "ex:company-a" }
}
]
}
This creates:
ex:company-a rdf:type schema:Organization
ex:company-a schema:name "Acme Corp"
ex:alice rdf:type schema:Person
ex:alice schema:name "Alice"
ex:alice schema:worksFor ex:company-a
Nested Objects
Create nested structures:
{
"@context": {
"ex": "http://example.org/ns/",
"schema": "http://schema.org/"
},
"@graph": [
{
"@id": "ex:alice",
"@type": "schema:Person",
"schema:name": "Alice",
"schema:address": {
"@id": "ex:alice-address",
"@type": "schema:PostalAddress",
"schema:streetAddress": "123 Main St",
"schema:addressLocality": "Springfield",
"schema:postalCode": "12345"
}
}
]
}
This creates two entities (alice and alice-address) linked by schema:address.
Multi-Valued Properties
Add multiple values for a property:
{
"@context": {
"ex": "http://example.org/ns/",
"schema": "http://schema.org/"
},
"@graph": [
{
"@id": "ex:alice",
"@type": "schema:Person",
"schema:name": "Alice",
"schema:email": ["alice@example.org", "alice@work.com"],
"schema:telephone": ["+1-555-0100", "+1-555-0101"]
}
]
}
Creates separate triples for each value:
ex:alice schema:email "alice@example.org"
ex:alice schema:email "alice@work.com"
ex:alice schema:telephone "+1-555-0100"
ex:alice schema:telephone "+1-555-0101"
Typed Literals
Dates
{
"@id": "ex:alice",
"schema:birthDate": {
"@value": "1994-05-15",
"@type": "xsd:date"
}
}
Timestamps
{
"@id": "ex:event",
"schema:startDate": {
"@value": "2024-01-22T10:30:00Z",
"@type": "xsd:dateTime"
}
}
Numbers
{
"@id": "ex:product",
"schema:price": {
"@value": "29.99",
"@type": "xsd:decimal"
}
}
Booleans
{
"@id": "ex:alice",
"schema:active": {
"@value": "true",
"@type": "xsd:boolean"
}
}
Or use native JSON boolean:
{
"@id": "ex:alice",
"schema:active": true
}
Language Tags
Add language-tagged strings:
{
"@id": "ex:alice",
"schema:name": {
"@value": "Alice",
"@language": "en"
},
"schema:description": [
{ "@value": "Software engineer", "@language": "en" },
{ "@value": "Ingénieure logicielle", "@language": "fr" },
{ "@value": "Softwareingenieurin", "@language": "de" }
]
}
Blank Nodes
Create entities without explicit IRIs:
{
"@context": {
"ex": "http://example.org/ns/",
"schema": "http://schema.org/"
},
"@graph": [
{
"@id": "ex:alice",
"schema:address": {
"@type": "schema:PostalAddress",
"schema:streetAddress": "123 Main St"
}
}
]
}
Fluree generates a unique IRI for the blank node address.
Adding to Existing Entities
Add properties to existing entities:
Initial Insert (t=1):
{
"@graph": [
{
"@id": "ex:alice",
"schema:name": "Alice"
}
]
}
Add Email (t=2):
{
"@graph": [
{
"@id": "ex:alice",
"schema:email": "alice@example.org"
}
]
}
After t=2, ex:alice has both name and email.
Insert Semantics
Additive by Default
Inserts are additive—they don't remove existing data:
t=1: INSERT { ex:alice schema:name "Alice" }
Result: ex:alice has name "Alice"
t=2: INSERT { ex:alice schema:age 30 }
Result: ex:alice has name "Alice" AND age 30
Duplicate Prevention
Inserting the same triple again is a no-op:
t=1: INSERT { ex:alice schema:name "Alice" }
t=2: INSERT { ex:alice schema:name "Alice" }
(No change—triple already exists)
Multi-Value Handling
Multiple values create multiple triples:
t=1: INSERT { ex:alice schema:email "alice@example.org" }
t=2: INSERT { ex:alice schema:email "alice@work.com" }
Result: ex:alice has TWO email values
IRI Generation
Explicit IRIs
Specify IRIs explicitly:
{
"@id": "ex:user-12345",
"schema:name": "Alice"
}
UUID-Based IRIs
Generate UUIDs for unique IRIs:
const uuid = crypto.randomUUID();
const entity = {
"@id": `ex:user-${uuid}`,
"schema:name": "Alice"
};
Content-Addressable IRIs
Use content hashing for deterministic IRIs:
const hash = sha256(JSON.stringify(data));
const entity = {
"@id": `ex:entity-${hash}`,
...data
};
Batch Inserts
Small Batches (Recommended)
{
"@graph": [
{ "@id": "ex:user-1", "schema:name": "Alice" },
{ "@id": "ex:user-2", "schema:name": "Bob" },
{ "@id": "ex:user-3", "schema:name": "Carol" }
// ... 100-1000 entities
]
}
Large Imports
For very large imports:
const batchSize = 1000;
for (let i = 0; i < entities.length; i += batchSize) {
const batch = entities.slice(i, i + batchSize);
await transact({ "@graph": batch });
// Optional: wait for indexing
await sleep(1000);
}
Error Handling
Common Insert Errors
Invalid IRI:
{
"error": "ValidationError",
"message": "Invalid IRI format",
"code": "INVALID_IRI"
}
Type Mismatch:
{
"error": "TypeError",
"message": "Expected number, got string",
"code": "TYPE_ERROR"
}
Constraint Violation:
{
"error": "ConstraintViolation",
"message": "Unique constraint violated",
"code": "CONSTRAINT_VIOLATION"
}
Validation Before Insert
Validate data before inserting:
function validateEntity(entity) {
if (!entity['@id']) {
throw new Error('Entity must have @id');
}
if (!isValidIRI(entity['@id'])) {
throw new Error('Invalid IRI format');
}
// Additional validation...
}
Best Practices
1. Use Meaningful IRIs
Good:
{ "@id": "ex:user-alice-12345" }
Bad:
{ "@id": "ex:1" }
2. Always Include Type
{
"@id": "ex:alice",
"@type": "schema:Person"
}
3. Use Appropriate Datatypes
{
"schema:age": 30,
"schema:price": 29.99,
"schema:active": true,
"schema:birthDate": { "@value": "1994-05-15", "@type": "xsd:date" }
}
4. Batch Related Entities
Insert related entities in same transaction:
{
"@graph": [
{ "@id": "ex:order-123", ... },
{ "@id": "ex:order-item-1", ... },
{ "@id": "ex:order-item-2", ... }
]
}
5. Use Consistent Namespaces
Define and use consistent namespace prefixes:
{
"@context": {
"app": "https://myapp.com/ns/",
"schema": "http://schema.org/"
}
}
6. Include Metadata
Add creation metadata:
{
"@id": "ex:alice",
"schema:name": "Alice",
"app:createdAt": "2024-01-22T10:00:00Z",
"app:createdBy": "user-admin"
}
7. Validate Before Insert
Always validate:
- JSON-LD syntax
- IRI formats
- Required fields
- Type constraints
Performance Tips
1. Batch Appropriately
- Recommended: 100-1000 entities per batch
- Too small: Many commits, slow
- Too large: Memory pressure, long commits
2. Monitor Indexing
Track indexing lag after large inserts:
curl http://localhost:8090/v1/fluree/info/mydb:main
# Check: t - index.t
3. Use Efficient IRIs
Short IRIs are more efficient:
Good: ex:user-123
Less efficient: https://example.org/very/long/path/user-123
4. Minimize Context Size
Use compact contexts:
{
"@context": {
"ex": "http://example.org/ns/",
"schema": "http://schema.org/"
}
}
Related Documentation
- Overview - Transaction overview
- Upsert - Replace mode inserts
- Update - Updating existing data
- Data Types - Supported datatypes
- API Endpoints - HTTP API details