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:1234
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:
12345678910
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(); |
1 2 | 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:
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:123456789101112131415161718
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:
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.
123456789
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:
123456789101112131415161718
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.
12345678910
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:123
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:
Client.DTOs.FieldValue emailFrom = documentDTO.Fields.Get(
"Email From"
);
-
Read a single choice field:12
Client.DTOs.FieldValue singleChoiceField = documentDTO.Fields.Get(
"Custodian"
);
Client.DTOs.Artifact singleChoice = (Client.DTOs.Artifact)singleChoiceField.Value;
-
Read a multi-choice field:12
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.
12345678910
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.
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.
123456789
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:
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.
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.
query.RelationalField =
new
Client.DTOs.FieldValue(
"Group Identifier"
);
- Request the Document fields you want to return.
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:
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.
123456789101112131415161718192021
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.
1234567891011//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:
Client.DTOs.Document doc =
new
Client.DTOs.Document(
this
.SampleDocument_ID);
- Specify the handler function to be used to handle the download failure event:
proxy.Failure += FileTransferFailureHandler;
The following is sample code sample for the FileTransferFailureHandler function:
12345private
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:
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.
123456789101112131415
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.12345678910
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.