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.
This example uploads a PDF report and shares it with a team group for collaborative review.
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 ();
This example performs a semantic search to find relevant information across all documents shared in a team graph.
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 ();
This example demonstrates how to track where a document has been shared and manage access.
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' );
This example shows how to upload multiple documents and track their processing status.
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 ( ' \n Batch Upload Summary:' );
console. log ( `✓ Successful: ${ successful . length }` );
console. log ( `✗ Failed: ${ failed . length }` );
console. log ( `Total chunks created: ${ totalChunks }` );
if (failed. length > 0 ) {
console. log ( ' \n Failed 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);
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
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
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
Overview - Document concepts and processing pipeline
Endpoints - Complete API reference
Technical Notes - Supported formats and troubleshooting
Scripts - Build serverless functions that search documents