# Add and Remove Content

## Collection: Add and Remove Content

### User Intent

"I want to add or remove content from collections"

### Operation

* **SDK Method**: `graphlit.addContentsToCollections()` or `graphlit.removeContentsFromCollection()`
* **GraphQL**: `addContentsToCollections` or `removeContentsFromCollection` mutation
* **Entity Type**: Collection
* **Common Use Cases**: Organize content, manage collection membership, dynamic categorization

### TypeScript (Canonical)

```typescript
import { Graphlit } from 'graphlit-client';
import {
  ContentTypes,
  EntityReferenceInput,
  FileTypes,
} from 'graphlit-client/dist/generated/graphql-types';

const graphlit = new Graphlit();

// Assumes you have a collection ID from creating a collection:
// const collection = await graphlit.createCollection({ name: "My Collection" });
// const collectionId = collection.createCollection.id;
const collection: EntityReferenceInput = { id: 'collection-id' };
const contents: EntityReferenceInput[] = [
  { id: 'content-id-1' },
  { id: 'content-id-2' },
  { id: 'content-id-3' },
];

// Add content to collection
await graphlit.addContentsToCollections(contents, [collection]);

console.log(`Added ${contents.length} items to collection`);

// Remove content from collection
await graphlit.removeContentsFromCollection([{ id: 'content-id-1' }], collection);

console.log('Removed 1 item from collection');

// Verify collection contents
const membership = await graphlit.queryContents({
  collections: [collection]
});

console.log(`Collection now has ${membership.contents.results.length} items`);
```

## Add content to collection (snake\_case)

await graphlit.client.add\_contents\_to\_collections( contents=\[{"id": content\_id} for content\_id in content\_ids], collections=\[{"id": collection\_id}] )

print(f"Added {len(content\_ids)} items to collection")

## Remove content from collection

await graphlit.client.remove\_contents\_from\_collection( contents=\[{"id": "content-id-1"}], collection={"id": collection\_id} )

print("Removed 1 item from collection")

````

**C#**:
```csharp
using Graphlit;

var client = new Graphlit();

var collectionId = "collection-id-here";
var contentIds = new[] { "content-id-1", "content-id-2", "content-id-3" };

// Add content to collection (PascalCase)
await graphlit.AddContentsToCollection(
    id: collectionId,
    contents: contentIds
);

Console.WriteLine($"Added {contentIds.Length} items to collection");

// Remove content from collection
await graphlit.RemoveContentsFromCollection(
    id: collectionId,
    contents: new[] { "content-id-1" }
);

Console.WriteLine("Removed 1 item from collection");
````

### Parameters

#### addContentsToCollections

* **`id`** (string): Collection ID
* **`contents`** (string\[]): Array of content IDs to add

#### removeContentsFromCollection

* **`collection`** (`EntityReferenceInput`): Target collection reference
* **`contents`** (`EntityReferenceInput[]`): Content references to remove

### Response

```typescript
{
  addContentsToCollections: {
    id: string;  // Collection ID
  }
}

{
  removeContentsFromCollection: {
    id: string;  // Collection ID
  }
}
```

### Developer Hints

#### Add vs Ingestion

**Two ways to add content to collections**:

```typescript
// 1. During ingestion (preferred for new content)
await graphlit.ingestUri(
  uri, undefined, undefined, undefined, true,
  undefined,  // workflow
  [{ id: collectionId }]  // collections - added during ingest
);

// 2. After ingestion (for existing content)
await graphlit.addContentsToCollections(
  [{ id: contentId }],
  [{ id: collectionId }]
);
```

#### Batch Operations

```typescript
// Add multiple content items at once
const contentIds = ['id-1', 'id-2', 'id-3', 'id-4', 'id-5'];

await graphlit.addContentsToCollections(
  contentIds.map((id) => ({ id })),
  [{ id: collectionId }]
);

console.log(`Added ${contentIds.length} items in single operation`);
```

#### Move Content Between Collections

```typescript
// Move from one collection to another
const contentId = 'content-id-here';
const fromCollectionId = 'collection-a';
const toCollectionId = 'collection-b';

// Remove from old collection
await graphlit.removeContentsFromCollection(
  [{ id: contentId }],
  { id: fromCollectionId }
);

// Add to new collection
await graphlit.addContentsToCollections(
  [{ id: contentId }],
  [{ id: toCollectionId }]
);

console.log('Content moved between collections');
```

#### Content Can Be in Multiple Collections

```typescript
// Same content in multiple collections (this is OK!)
const contentId = 'content-id-here';

await graphlit.addContentsToCollections(
  [{ id: contentId }],
  [
    { id: 'collection-a' },
    { id: 'collection-b' },
    { id: 'collection-c' }
  ]
);

// Content now appears in 3 collections
```

### Variations

#### 1. Add Single Item

Add one content item:

```typescript
await graphlit.addContentsToCollections(
  [{ id: contentId }],
  [{ id: collectionId }]
);
```

#### 2. Add Multiple Items

Batch add:

```typescript
const contentIds = ['id-1', 'id-2', 'id-3'];

await graphlit.addContentsToCollections(
  contentIds.map((id) => ({ id })),
  [{ id: collectionId }]
);
```

#### 3. Remove Items

Remove from collection:

```typescript
await graphlit.removeContentsFromCollection(
  [
    { id: 'content-id-1' },
    { id: 'content-id-2' }
  ],
  { id: collectionId }
);
```

#### 4. Add All Content from Query

Add filtered content:

```typescript
// Query content to add
const contents = await graphlit.queryContents({
  search: 'API documentation',
  types: [ContentTypes.Page]
});

// Extract IDs
const contentRefs = contents.contents.results.map((c) => ({ id: c.id }));

// Add to collection
await graphlit.addContentsToCollections(contentRefs, [{ id: collectionId }]);

console.log(`Added ${contentIds.length} API docs to collection`);
```

#### 5. Reorganize Collections

Move content based on criteria:

```typescript
// Get all content in collection
const contents = await graphlit.queryContents({
  collections: [{ id: oldCollectionId }],
  fileTypes: [FileTypes.Pdf]
});

// Move PDFs to new collection
const pdfRefs = contents.contents.results.map((c) => ({ id: c.id }));

await graphlit.removeContentsFromCollection(pdfRefs, { id: oldCollectionId });
await graphlit.addContentsToCollections(pdfRefs, [{ id: newCollectionId }]);

console.log(`Moved ${pdfIds.length} PDFs to new collection`);
```

#### 6. Clear Collection

Remove all content:

```typescript
// Get all content IDs in collection
const existing = await graphlit.queryContents({
  collections: [{ id: collectionId }]
});

const entries = existing.contents.results.map((c) => ({ id: c.id }));

await graphlit.removeContentsFromCollection(entries, { id: collectionId });

console.log(`Cleared collection (removed ${entries.length} items)`);
```

### Common Issues

**Issue**: `Collection not found` error\
**Solution**: Verify collection ID is correct using `queryCollections()`.

**Issue**: `Content not found` error\
**Solution**: Verify content IDs exist. Content may have been deleted.

**Issue**: Content appears in multiple collections\
**Solution**: This is by design. Content can belong to multiple collections. Remove from unwanted collections.

**Issue**: Changes not visible immediately\
**Solution**: Changes are immediate. Re-query to see updates.

### Production Example

**Dynamic content organization**:

```typescript
// Organize content by file type
async function organizeByFileType() {
  // Create collections by type
  const pdfCollection = await graphlit.createCollection({ name: 'PDFs' });
  const docCollection = await graphlit.createCollection({ name: 'Documents' });
  const imageCollection = await graphlit.createCollection({ name: 'Images' });
  
  // Query all content
  const allContent = await graphlit.queryContents();
  
  // Organize by type
  for (const content of allContent.contents.results) {
    if (content.fileType === FileTypes.Pdf) {
      await graphlit.addContentsToCollections(
        [{ id: content.id }],
        [{ id: pdfCollection.createCollection.id }]
      );
    } else if (content.fileType === FileTypes.Document) {
      await graphlit.addContentsToCollections(
        [{ id: content.id }],
        [{ id: docCollection.createCollection.id }]
      );
    } else if (content.fileType === FileTypes.Image) {
      await graphlit.addContentsToCollections(
        [{ id: content.id }],
        [{ id: imageCollection.createCollection.id }]
      );
    }
  }
  
  console.log(' Content organized by file type');
}

await organizeByFileType();
```

**Tagging system with collections**:

```typescript
// Use collections as tags
async function tagContent(contentId: string, tags: string[]) {
  for (const tag of tags) {
    // Find or create collection for tag
    const collections = await graphlit.queryCollections({ search: tag });
    
    let collectionId: string;
    
    if (collections.collections.results.length > 0) {
      collectionId = collections.collections.results[0].id;
    } else {
      const newColl = await graphlit.createCollection({ name: tag });
      collectionId = newColl.createCollection.id;
    }
    
    // Add content to collection
    await graphlit.addContentsToCollections(
      [{ id: contentId }],
      [{ id: collectionId }]
    );
  }
  
  console.log(`Tagged content with: ${tags.join(', ')}`);
}

// Usage
await tagContent('content-123', ['important', 'customer-facing', 'q4-2024']);
```
