As part of the Relativity Services API (RSAPI) Deprecation, content on this page referring to the RSAPI and the Patient Tracker application is in the process of being deprecated and will no longer be supported. For more information and alternative APIs, see RSAPI deprecation process.

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:

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:

  1. Instantiate the client proxy object:
    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.

  2. Set the workspace ID in the APIOptions object. This specifies the Relativity workspace where the document will be added:
  3. proxy.APIOptions.WorkspaceID = this.SampleWorkspace_ID;
  4. Instantiate the Document object:
  5. Client.DTOs.Document document = new Client.DTOs.Document();
  6. Set the required field values: RelativityNativeFileLocation (the local path for the document native uploaded to Relativity) and TextIdentifier (document name):
  7. 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.

  8. Set the optional parent artifact ID.
  9. document.ParentArtifact = new Client.DTOs.Artifact(this.SampleFolder_ID); 
  10. Call the CreateSingle() method of the DocumentRepository object passing it the populated Document object. Use a try/catch block in case the operation fails:
    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.

Create multiple documents

To create multiple documents in a Relativity workspace:

  1. Instantiate the client proxy and set the workspace ID in the APIOptions object as shown in Create a single document.
  2. Instantiate a list of Document objects:
    List<Client.DTOs.Document> documentsToCreate = new List<Client.DTOs.Document>();
  3. Add the Document objects to the list. This example uses an iterative loop to add ten (10) document objects:
    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.

  4. Instantiate the WriteResultSet object for the create operation:
    Client.DTOs.WriteResultSet<Client.DTOs.Document> resultSet = new Client.DTOs.WriteResultSet<Client.DTOs.Document>();
  5. 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.
    try
    {
        resultSet = proxy.Repositories.Document.Create(documentsToCreate);
    }
    catch (Exception ex)
    {
        Console.WriteLine("The create failed. {0}", resultSet.Message);
        return false;
    }
    
  6. 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:
    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:

  1. Instantiate the client proxy and set the workspace ID in the APIOptions object as shown in Create a single document.
  2. 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.
    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;
    }   
    
  3. Read the basic object fields using the object properties when the Document object returns. For example, ArtifactID and TextIdentifier:
    int artifactID = documentDTO.ArtifactID;
    int parentArtifactID = documentDTO.ParentArtifact.ArtifactID;
    string controlNumber = documentDTO.TextIdentifier;
  4. 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");
  5. Read a single choice field:
    Client.DTOs.FieldValue singleChoiceField = documentDTO.Fields.Get("Custodian");
    Client.DTOs.Artifact singleChoice = (Client.DTOs.Artifact)singleChoiceField.Value;
  6. Read a multi-choice field:
    Client.DTOs.FieldValue analyticsField = documentDTO.Fields.Get("Analytics Index");
    Client.DTOs.MultiChoiceFieldValueList multiChoiceList = analyticsField.ValueAsMultipleChoice;
  7. Note: A ReadSingle request doesn't include extracted text.

Update document fields

To update document field values:

  1. Instantiate the client proxy and set the workspace ID in the APIOptions object as shown in Create a single document.
  2. 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.
    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.

  3. 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());
  4. Update the document by calling the UpdateSingle() method of the DocumentRepository object. Use a try/catch block in case the operation fails.
    try
    {
    	proxy.Repositories.Document.UpdateSingle(documentDTO);
    }
    catch (Client.APIException ex)
    {
        Console.WriteLine("An error occurred: {0}", ex.Message);
        return false;
    }

Query extracted text

To query the extracted text field of document objects:

  1. Instantiate the client proxy and set the workspace ID in the APIOptions object as shown in Create a single document.
  2. Instantiate the Query object:
    Client.DTOs.Query<Client.DTOs.Document> query = new Client.DTOs.Query<Client.DTOs.Document>();
  3. 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");
  4. 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");
  5. 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.

  6. Instantiate the QueryResultSet object:
    Client.DTOs.QueryResultSet<Client.DTOs.Document> resultSet = new QueryResultSet<Document>();
  7. Call the Query() method of the DocumentRepository object passing it the populated Query object. Use a try/catch block in case the operation fails.
    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.

    //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:

  1. Instantiate the client proxy and set the workspace ID in the APIOptions object as shown in Create a single document.
  2. 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);
  3. 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:

    private 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);
    }
  4. Declare the document native response object as a KeyValuePair<TKey, TValue> Structure:
    KeyValuePair<DownloadResponse, Stream> documentNativeResponse;
  5. Call the Download() method of the DocumentRepository object passing it the Document object. Use a try/catch block in case the operation fails.
    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;
    }
  6. Initialize a Stream object to the value of the document native file and write the stream to the file system.
    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.

Additional Resources

DevHelp Community GitHub Release Notes NuGet

Share knowledge with the Relativity developer community.

Access tools and resources to build an application.

Review the most recent product release notes.

Create .NET Apps faster with NuGet.