Work with documents and extracted text
In Relativity documents are primary case objects that enable the legal review. The Services API includes a set of interfaces for customizing your document workflow.
This page provides detailed explanations of the programmatic steps for the following common document tasks:
- Create documents
- Read documents
- Update document fields
- Query extracted text
- Download the native file
For complete document operations reference and code samples, see Document in RSAPI reference for .NET.
Create documents
You can create Relativity workspace documents using both regular multi-artifact and single-artifact patterns. For more information about DTO artifact access patterns, see Single vs. multiple artifact access pattern.
Create a single document
To create a document:
- Instantiate the client proxy object:Copy
using (IRSAPIClient proxy = helper.GetServicesManager().CreateProxy<IRSAPIClient>(ExecutionIdentity.System))
{
//All operations on the Services API DTO objects must be enclosed in the using block
}Note: In this example the proxy object instantiates using the IRSAPIClient helper class with System execution identity. For more information, see Create the proxy using the Relativity API Helpers. Also note that all subsequent operations with Relativity objects perform within the using block.
- Set the workspace ID in the APIOptions object. This specifies the Relativity workspace where the document will be added:
- Instantiate the Document object:
- Set the required field values: RelativityNativeFileLocation (the local path for the document native uploaded to Relativity) and TextIdentifier (document name):
- Set the optional parent artifact ID.
- Call the CreateSingle() method of the DocumentRepository object passing it the populated Document object. Use a try/catch block in case the operation fails:
Copy
try
{
int documentID = proxy.Repositories.Document.CreateSingle(document);
Console.WriteLine("New Document Artifact ID: {0}", documentID);
}
catch (APIException ex)
{
Console.WriteLine("An error occurred: {0}", ex.Message);
return false;
}If the document successfully creates, the integer value of its Artifact ID returns.
If the operations fails, kCura.Relativity.Client.APIException returns. The Message property of the exception indicates the error.
proxy.APIOptions.WorkspaceID = this.SampleWorkspace_ID;
Client.DTOs.Document document = new Client.DTOs.Document();
document.RelativityNativeFileLocation = string.Format("{0}\\SampleFiles\\{1}", Directory.GetCurrentDirectory(), "LoremIpsum.docx");
document.TextIdentifier = Guid.NewGuid().ToString();
Note: The name of the identifier field changes depending on the workspace, so use the TextIdentifier property. In the example above the identifier is set to a GUID. In Relativity it is a common practice to set the value to the native file name or some other human-readable value, for example, Case_Document_12_31_2000-00001.
document.ParentArtifact = new Client.DTOs.Artifact(this.SampleFolder_ID);
Create multiple documents
To create multiple documents in a Relativity workspace:
- Instantiate the client proxy and set the workspace ID in the APIOptions object as shown in Create a single document.
- Instantiate a list of Document objects:
Copy
List<Client.DTOs.Document> documentsToCreate = new List<Client.DTOs.Document>();
- Add the Document objects to the list. This example uses an iterative loop to add ten (10) document objects:Copy
for (int i = 0; i < 10; i++)
{
//Create a Document DTO
Client.DTOs.Document document = new Client.DTOs.Document();
//Set primary fields
document.RelativityNativeFileLocation = string.Format("{0}\\SampleFiles\\{1}", Directory.GetCurrentDirectory(), "LoremIpsum.docx");
//NOTE: The name of the identifier field will change depending on the workspace, so use the TextIdentifier property.
//The text identifier of the sample data is being set to a random string so that sample data can be debugged
//and never causes collisions. You can set this to the file name or any string that you want
document.TextIdentifier = Guid.NewGuid().ToString();
//Set secondary fields
document.ParentArtifact = new Client.DTOs.Artifact(this.SampleFolder_ID);
//Add the create request to the list of requests
documentsToCreate.Add(document);
}Note: The required RelativityNativeFileLocation (native file path) and TextIdentifier (document name) field values in this example are set in the same way as in the example in Create a single document. As a result, the same native file LoremIpsum.docx uploads for all created documents and the document name set to a GUID value.
- Instantiate the WriteResultSet object for the create operation:
Copy
Client.DTOs.WriteResultSet<Client.DTOs.Document> resultSet = new Client.DTOs.WriteResultSet<Client.DTOs.Document>();
- Call the Create() method of the DocumentRepository object, passing it the populated Document objects list. A WriteResultSet object instantiates to the result of the documents create operation. Use a try/catch block in case the operation fails.
Copy
try
{
resultSet = proxy.Repositories.Document.Create(documentsToCreate);
}
catch (Exception ex)
{
Console.WriteLine("The create failed. {0}", resultSet.Message);
return false;
} - Evaluate the Success property of the Write ResultSet object by checking the result of the create operation and iterating through the objects in the Results collection:
Copy
if (resultSet.Success)
{
//Check the results
int succeed = 0;
foreach (Result<Client.DTOs.Document> doc in resultSet.Results)
{
if (doc.Success)
{
succeed++;
}
}
Console.WriteLine("{0} Documents created", succeed);
}
else
{
Console.WriteLine("The create failed. {0}", resultSet.Message);
return false;
}If all documents create successfully, the Success property returns as True for every object in the collection.
Read documents
You can read Relativity workspace documents with both regular multi-artifact and single-artifact patterns. For more information about DTO artifact access patterns, see Single vs. multiple artifact access pattern.
To read a document:
- Instantiate the client proxy and set the workspace ID in the APIOptions object as shown in Create a single document.
- Call the ReadSingle() method of the DocumentRepository object passing it the document ID to read the document. Use a try/catch block in case the operation fails.
Copy
try
{
Client.DTOs.Document documentDTO = proxy.Repositories.Document.ReadSingle(this.SampleDocument_ID);
//The rest of the document read operation
catch (Exception ex)
{
Console.WriteLine("The create failed. {0}", resultSet.Message);
return false;
} - Read the basic object fields using the object properties when the Document object returns. For example, ArtifactID and TextIdentifier:Copy
int artifactID = documentDTO.ArtifactID;
int parentArtifactID = documentDTO.ParentArtifact.ArtifactID;
string controlNumber = documentDTO.TextIdentifier; - Read the Email From field using the field name passed to the Get() method of the Fields collection:Copy
Client.DTOs.FieldValue emailFrom = documentDTO.Fields.Get("Email From");
-
Read a single choice field:Copy
Client.DTOs.FieldValue singleChoiceField = documentDTO.Fields.Get("Custodian");
Client.DTOs.Artifact singleChoice = (Client.DTOs.Artifact)singleChoiceField.Value; -
Read a multi-choice field:Copy
Client.DTOs.FieldValue analyticsField = documentDTO.Fields.Get("Analytics Index");
Client.DTOs.MultiChoiceFieldValueList multiChoiceList = analyticsField.ValueAsMultipleChoice;
Note: A ReadSingle request doesn't include extracted text.
Update document fields
To update document field values:
- Instantiate the client proxy and set the workspace ID in the APIOptions object as shown in Create a single document.
- Call the ReadSingle() method of the DocumentRepository object passing it the document Artifact ID. Instantiate a Document object to the results of the read operation. Use a try/catch block in case the operation fails.
Copy
try
{
Client.DTOs.Document documentDTO = proxy.Repositories.Document.ReadSingle(this.SampleDocument_ID);
}
catch (Client.APIException ex)
{
Console.WriteLine(string.Format("An error occurred: {0}", ex.Message));
return false;
}Note: You can create the document manually rather than read it.
- Change the document object TextIdentifier (name) field value. Note that in this example it is set to a GUID, but you can set it to the document file name or any other string.Copy
documentDTO.TextIdentifier = string.Format("API Sample (Updated) {0}", Guid.NewGuid());
- Update the document by calling the UpdateSingle() method of the DocumentRepository object. Use a try/catch block in case the operation fails.
Copy
try
{
proxy.Repositories.Document.UpdateSingle(documentDTO);
}
catch (Client.APIException ex)
{
Console.WriteLine("An error occurred: {0}", ex.Message);
return false;
}<br />
Query extracted text
To query the extracted text field of document objects:
- Instantiate the client proxy and set the workspace ID in the APIOptions object as shown in Create a single document.
- Instantiate the Query object: Copy
Client.DTOs.Query<Client.DTOs.Document> query = new Client.DTOs.Query<Client.DTOs.Document>();
- Define the query condition using the TextQueryCondition object. You must specify the name of the queried field, the condition operator (in this example, Like), and the string value to look for.Copy
query.Condition = new TextCondition("Extracted Text", Client.TextConditionEnum.Like, "Lorem Ipsum");
- Specify the relational field for the query. A relational field identifies a group of related documents, such as families, duplicates, or near duplicates. Copy
query.RelationalField = new Client.DTOs.FieldValue("Group Identifier");
- Request the Document fields you want to return. Copy
query.Fields.Add(new Client.DTOs.FieldValue(Client.DTOs.FolderFieldNames.TextIdentifier));
Note: It's a best practice to specify fields to return rather than using AllFields. This keeps the data return predictable in large environments with many fields.
-
Instantiate the QueryResultSet object: Copy
Client.DTOs.QueryResultSet<Client.DTOs.Document> resultSet = new QueryResultSet<Document>();
- Call the Query() method of the DocumentRepository object passing it the populated Query object. Use a try/catch block in case the operation fails.
Copy
try
{
resultSet = proxy.Repositories.Document.Query(query, 0);
}
catch (Exception ex)
{
Console.WriteLine(string.Format("An error occurred: {0}", ex.Message));
return false;
}
//Check the success
if (resultSet.Success)
{
Console.WriteLine(string.Format("Number of Documents returned: {0}", resultSet.TotalCount));
return true;
}
else
{
Console.WriteLine("The create failed. {0}", resultSet.Message);
return false;
}Use the document objects in the result set for further processing. In this example, the number of query results returns using the TotalCount property of the QueryResultSet object.
Copy//Check the success
if (resultSet.Success)
{
Console.WriteLine(string.Format("Number of Documents returned: {0}", resultSet.TotalCount));
return true;
}
else
{
Console.WriteLine("The create failed. {0}", resultSet.Message);
return false;
}
Download the native file
To download the native file of a Relativity document:
- Instantiate the client proxy and set the workspace ID in the APIOptions object as shown in Create a single document.
- Initialize a Document DTO with the ArtifactId of the document which has a native file:Copy
Client.DTOs.Document doc = new Client.DTOs.Document(this.SampleDocument_ID);
- Specify the handler function to be used to handle the download failure event: Copy
proxy.Failure += FileTransferFailureHandler;
The following is sample code sample for the FileTransferFailureHandler function:
Copyprivate void FileTransferFailureHandler(FailureEventArgs eventArgs)
{
string err = string.Format("The following error occurred during the download for the document with ArtifactId {0}: {1}", eventArgs.TargetField.ObjectArtifactId, eventArgs.Exception);
this.Logger.LogMessage(Client.SamplesLibrary.Logging.LogLevel.Error, new StackFrame(0).GetMethod().Name, err, this.GetType().Name);
} - Declare the document native response object as a KeyValuePair<TKey, TValue> Structure:
Copy
KeyValuePair<DownloadResponse, Stream> documentNativeResponse;
- Call the Download() method of the DocumentRepository object passing it the Document object. Use a try/catch block in case the operation fails.
Copy
try
{
documentNativeResponse = proxy.Repositories.Document.DownloadNative(doc);
}
catch (Exception ex)
{
// Something went wrong while trying to download the document
this.Logger.LogMessage(Client.SamplesLibrary.Logging.LogLevel.Error, new StackFrame(0).GetMethod().Name, ex.Message, this.GetType().Name);
return false;
}
//A 'null' Key & Value from the response indicates failure
if (!(documentNativeResponse.Key != null && documentNativeResponse.Value != null))
{
return false;
} - Initialize a Stream object to the value of the document native file and write the stream to the file system.Copy
Stream docStream = documentNativeResponse.Value;
var nativeFileName = documentNativeResponse.Key.Metadata.FileName;
using (FileStream fileStream = File.Create("C:\\RelativityDownloads\\DocumentNatives\\" + nativeFileName, (int)docStream.Length))
{
docStream.Seek(0, 0);
byte[] bytesInStream = new byte[docStream.Length];
docStream.Read(bytesInStream, 0, bytesInStream.Length);
fileStream.Write(bytesInStream, 0, bytesInStream.Length);
}Note: You must use the Seek() method to set the position to the beginning of the stream.