The M-Files Community will be updated on Tuesday, April 2, 2024 at 10:00 AM EST / 2:00 PM GMT and the update is expected to last for several hours. The site will be unavailable during this time.

search for class document objects per project comapi c#

I'm trying to write a report of document objects by class per project using the comapi in C#. I've wrote a search condition that iterates through each object class looking for the property definition id for the project but I'm not getting the results I'm expecting. I need some guidance as to what I'm doing wrong


ObjTypes oObjectTypes = mfServerApplication.LogInToVault(GetVaultGuid).ObjectTypeOperations.GetObjectTypes();
foreach (ObjType oObjType in oObjectTypes)
{
//foreach (PropertyDef propDef in propDefs)
//{
int propertydef = 0;
var searchConditions = new SearchConditions();

// Add an object type filter.
{
// Create the condition.
var condition = new SearchCondition();

// Set the expression.
condition.Expression.SetStatusValueExpression(MFStatusType.MFStatusTypeObjectTypeID);

// Set the condition.
condition.ConditionType = MFConditionType.MFConditionTypeEqual;

// Set the value.
condition.TypedValue.SetValue(MFilesAPI.MFDataType.MFDatatypeLookup,
oObjType.ID);

// Add the condition to the collection.
searchConditions.Add(-1, condition);
}

// Add a "not deleted" filter.
{
// Create the condition.
var condition = new SearchCondition();

// Set the expression.
condition.Expression.SetStatusValueExpression(MFStatusType.MFStatusTypeDeleted);

// Set the condition.
condition.ConditionType = MFConditionType.MFConditionTypeEqual;

// Set the value.
condition.TypedValue.SetValue(MFilesAPI.MFDataType.MFDatatypeBoolean, false);

// Add the condition to the collection.
searchConditions.Add(-1, condition);
}


{
// Create the condition.
var condition = new SearchCondition();


//condition.Expression.SetPropertyValueExpression(propDef.ID, MFParentChildBehavior.MFParentChildBehaviorNone);
condition.Expression.SetPropertyValueExpression(propertydef, MFParentChildBehavior.MFParentChildBehaviorNone);

// Set the condition.
condition.ConditionType = MFConditionType.MFConditionTypeEqual;
//1454 is the Arm Project id
condition.TypedValue.SetValue(MFDataType.MFDatatypeMultiSelectLookup, 1454);


var customerObjectTypeIndirectionLevel = new PropertyDefOrObjectType();
customerObjectTypeIndirectionLevel.PropertyDef = false; // We do not care which property definition is used.
customerObjectTypeIndirectionLevel.ID = oObjType.ID; // Instead care which object type it is related to.
condition.Expression.IndirectionLevels.Add(-1, customerObjectTypeIndirectionLevel);

// Add the condition to the collection.
searchConditions.Add(-1, condition);
}

ObjectSearchResults searchRes = mfServerApplication.LogInToVault(GetVaultGuid).ObjectSearchOperations.SearchForObjectsByConditionsEx(searchConditions,
MFSearchFlags.MFSearchFlagNone, SortResults: false);

foreach (var results in searchRes)
{

Console.WriteLine(results);

}
}

  • What do you mean that you don't get what you expect?  There's a couple of odd things here (e.g. the property definition seems to be hard-coded to 0 - name - but the typed value being searched against is a multi-select lookup, and I am not sure that you need indirection), but I'm not sure exactly what the issue is you're seeing.

  • I guess thats my question is if I'm reference groupings like that, documents grouped by projects, do I need that level of indirection to associate those two things in my search?

  • Indirections aren't used for groupings.

    Consider an example where you want to search for all "contacts whose company is based in the UK".  In that case the property you want to search on (country) is not on the contact itself, but on a related object (the company).  Indirection levels are used to express that relationship.  There's some more details here: Search conditions in the M-Files API.

    You cannot directly perform a "group by" within an API search.  I think you have three options:

    1. Search for all documents, retrieve the properties for them, and then perform the grouping in your calling application.
      1. Note that the search results have a practical limit though, so in large vaults you may not be able to get them all at once.
      2. Note also that you'll want to use the "GetPropertiesOfMultipleObjects" API method to retrieve batches of properties from the vault, rather than querying one-by-one.
    2. Retrieve the projects you're interested in from the API with one search, then use that to execute one or more additional queries to retrieve the documents.
      1. You could literally run one search per project; this may be good if the number of documents per project is high.
      2. Or you could perhaps create a "one of" search condition to find all documents where the "project" is "one of" a selection of projects; note again the search limit though, so this may also be a concern.
    3. Use a reporting database.

    Honestly: probably the best way to do this is to use a reporting database.  The M-Files APIs aren't great at set-based queries, but SQL definitely is.

  • we do have access to a reporting database but it doesn't seem to be a complete dataset which is why I was exploring this avenue. Thank you Craig for helping me understand that. 

  • I'd work with your M-Files administrator or reseller. You can configure what is exported and the frequency. Perhaps one or the other needs tweaking.

    I'd definitely go down this route if it's available to you, especially if your vault is large.