Mirra
SDK ReferenceDocuments

Document Examples

Practical examples for uploading, searching, and managing documents

Documents enable you to upload, process, and semantically search files within your knowledge graph. These examples demonstrate common document management patterns.

Upload and Share a Document

This example uploads a PDF report and shares it with a team group for collaborative review.

TypeScript

import { MirraSDK } from '@mirra-messenger/sdk';
import { readFileSync } from 'fs';
 
const mirra = new MirraSDK({
  apiKey: process.env.MIRRA_API_KEY
});
 
async function uploadAndShare() {
  // Read and encode the file
  const fileBuffer = readFileSync('./reports/q4-2024.pdf');
  const base64File = fileBuffer.toString('base64');
 
  // Upload to personal graph
  const uploadResult = await mirra.documents.upload({
    file: base64File,
    filename: 'q4-2024.pdf',
    mimeType: 'application/pdf',
    title: 'Q4 2024 Financial Report',
    author: 'Finance Team',
    productTags: ['finance', 'quarterly', '2024-Q4']
  });
 
  console.log(`Document uploaded: ${uploadResult.documentId}`);
  console.log(`Created ${uploadResult.chunkCount} chunks`);
 
  // Share with team group
  const shareResult = await mirra.documents.share({
    documentId: uploadResult.documentId,
    targetGraphId: 'group:team-finance',
    shareReason: 'For quarterly review meeting on Dec 15'
  });
 
  console.log(`Shared with ${shareResult.graphIds.length} graphs`);
}
 
uploadAndShare();

Search Across Team Documents

This example performs a semantic search to find relevant information across all documents shared in a team graph.

TypeScript

async function searchTeamDocs() {
  const results = await mirra.documents.search({
    query: 'What were the key revenue drivers in Q4?',
    graphId: 'group:team-finance',
    limit: 5,
    threshold: 0.75
  });
 
  console.log(`Found ${results.count} relevant chunks:\n`);
 
  results.results.forEach((result, index) => {
    console.log(`${index + 1}. [Score: ${result.score.toFixed(3)}] ${result.documentName}`);
    console.log(`   Page ${result.pageNumber}, Position ${result.position}`);
    console.log(`   "${result.content.substring(0, 150)}..."\n`);
  });
}
 
searchTeamDocs();

Track Document Sharing

This example demonstrates how to track where a document has been shared and manage access.

TypeScript

async function manageDocumentAccess(documentId: string) {
  // List all graphs where document is shared
  const graphsList = await mirra.documents.listGraphs(documentId);
 
  console.log(`Document "${documentId}" is shared in ${graphsList.graphs.length} graphs:\n`);
 
  graphsList.graphs.forEach(graph => {
    const isPrimary = graph.isPrimary ? ' (PRIMARY)' : '';
    console.log(`- ${graph.graphName}${isPrimary}`);
    console.log(`  Type: ${graph.graphType}`);
    console.log(`  Shared by: ${graph.sharedByUserId}`);
    console.log(`  Shared at: ${new Date(graph.sharedAt).toLocaleString()}`);
    if (graph.shareReason) {
      console.log(`  Reason: ${graph.shareReason}`);
    }
    console.log();
  });
 
  // Remove access from a specific group
  const groupToRemove = graphsList.graphs.find(
    g => g.graphType === 'group' && !g.isPrimary
  );
 
  if (groupToRemove) {
    const unshareResult = await mirra.documents.unshare({
      documentId,
      graphId: groupToRemove.graphId
    });
 
    console.log(`Removed access from ${groupToRemove.graphName}`);
    console.log(`Document now in ${unshareResult.graphIds.length} graphs`);
  }
}
 
manageDocumentAccess('doc_abc123');

Batch Document Processing

This example shows how to upload multiple documents and track their processing status.

TypeScript

async function uploadMultipleDocs(filePaths: string[]) {
  const uploadPromises = filePaths.map(async (filePath) => {
    const fileBuffer = readFileSync(filePath);
    const base64File = fileBuffer.toString('base64');
    const filename = filePath.split('/').pop()!;
    
    // Determine MIME type based on extension
    const ext = filename.split('.').pop()?.toLowerCase();
    const mimeTypes: Record<string, string> = {
      'pdf': 'application/pdf',
      'docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
      'txt': 'text/plain',
      'md': 'text/markdown'
    };
 
    try {
      const result = await mirra.documents.upload({
        file: base64File,
        filename,
        mimeType: mimeTypes[ext!] || 'text/plain',
        productTags: ['batch-upload', '2024-12']
      });
 
      return {
        filename,
        success: true,
        documentId: result.documentId,
        chunks: result.chunkCount,
        processingTime: result.processingTimeMs
      };
    } catch (error) {
      return {
        filename,
        success: false,
        error: error.message
      };
    }
  });
 
  const results = await Promise.all(uploadPromises);
 
  // Summary
  const successful = results.filter(r => r.success);
  const failed = results.filter(r => !r.success);
  const totalChunks = successful.reduce((sum, r) => sum + (r.chunks || 0), 0);
 
  console.log('\nBatch Upload Summary:');
  console.log(`✓ Successful: ${successful.length}`);
  console.log(`✗ Failed: ${failed.length}`);
  console.log(`Total chunks created: ${totalChunks}`);
  
  if (failed.length > 0) {
    console.log('\nFailed uploads:');
    failed.forEach(f => {
      console.log(`- ${f.filename}: ${f.error}`);
    });
  }
 
  return results;
}
 
const filePaths = [
  './docs/report-1.pdf',
  './docs/report-2.pdf',
  './docs/notes.txt',
  './docs/summary.md'
];
 
uploadMultipleDocs(filePaths);

Best Practices

Document Organization

  • Use descriptive filenames - Include dates, versions, and context in filenames
  • Add metadata - Always provide title, author, and productTags for better organization
  • Tag consistently - Develop a tagging taxonomy for your team and use it consistently
  • Version control - Include version numbers in titles or tags when uploading new versions

Search Optimization

  • Query length - Use 5-15 word queries for best results
  • Natural language - Phrase queries as questions or statements, not keyword lists
  • Adjust threshold - Start with 0.7 and adjust based on precision/recall needs
  • Limit appropriately - Use smaller limits (5-10) for high-precision needs

Access Control

  • Default to personal - Upload to your personal graph first, then share selectively
  • Document sharing reasons - Always provide a shareReason to track why documents were shared
  • Regular audits - Periodically review listGraphs() to ensure documents aren't over-shared
  • Unshare when done - Remove document access from graphs when collaboration is complete

See Also

  • Overview - Document concepts and processing pipeline
  • Endpoints - Complete API reference
  • Technical Notes - Supported formats and troubleshooting
  • Scripts - Build serverless functions that search documents

On this page