public static ObjectSearchResults SearchObjects(Vault vault, int objType, int?classId, SearchConditions otherConditions, bool deleted = false) { var scs = otherConditions != null?otherConditions.Clone() : new SearchConditions(); AddBaseConditions(scs, objType, classId, deleted); return(vault.ObjectSearchOperations.SearchForObjectsByConditionsEx( scs, MFSearchFlags.MFSearchFlagNone, false, 0, 0)); }
/// <summary> /// Returns whether there are objects in the vault that have a higher internal Id than /// the current segment. /// </summary> /// <param name="vaultObjectSearchOperations">The search operations object to query with.</param> /// <param name="searchConditions">The search conditions to execute.</param> /// <param name="searchFlags">Any search flags to execute (note that the order will not be respected).</param> /// <param name="segment">The zero-based index of the segment to return data for.</param> /// <param name="itemsPerSegment">The number of items to include in each segment. See <see cref="DefaultNumberOfItemsInSegment"/>.</param> /// <returns>true if there is at least one, false if there are none.</returns> private static bool HasMoreResults(this IVaultObjectSearchOperations vaultObjectSearchOperations, SearchConditions searchConditions, int segment, MFSearchFlags searchFlags = MFSearchFlags.MFSearchFlagDisableRelevancyRanking, int itemsPerSegment = IVaultObjectSearchOperationsExtensionMethods.DefaultNumberOfItemsInSegment) { // Sanity. if (null == vaultObjectSearchOperations) { throw new ArgumentNullException(nameof(vaultObjectSearchOperations)); } if (null == searchConditions) { throw new ArgumentNullException(nameof(searchConditions)); } if (segment <= 0) { segment = 0; } if (itemsPerSegment <= 0) { itemsPerSegment = IVaultObjectSearchOperationsExtensionMethods.DefaultNumberOfItemsInSegment; } // There are more results if there are any objects that meet the search criteria, with // an Id greater than the current segment range. // Clone the search conditions (so we can add object id condition). var internalSearchConditions = searchConditions.Clone(); // Add search condition: // Id at least (segment * itemsPerSegment) internalSearchConditions.AddMinimumObjectIdSearchCondition(segment * itemsPerSegment); // If we get zero items then there are no more results. var results = vaultObjectSearchOperations.SearchForObjectsByConditionsEx( internalSearchConditions, // Our search conditions. searchFlags, SortResults: false, // Don't bother attempting to sort them. MaxResultCount: 1, // We only need to know if there is at least one, nothing more. SearchTimeoutInSeconds: 0); // Did we only get one? return(0 != results.Count); }
private static ObjectVersions SearchObjectsByClass(Vault vault, int classId, SearchConditions searchConditions = null) { SearchConditions scs = searchConditions == null ? new SearchConditions() : searchConditions.Clone(); //对象类别 var conditionClass = new SearchCondition(); conditionClass.ConditionType = MFConditionType.MFConditionTypeEqual; conditionClass.Expression.DataPropertyValuePropertyDef = 100; conditionClass.TypedValue.SetValue(MFDataType.MFDatatypeLookup, classId); scs.Add(-1, conditionClass); //是否删除 var conditionDeleted = new SearchCondition(); conditionDeleted.ConditionType = MFConditionType.MFConditionTypeEqual; conditionDeleted.Expression.DataStatusValueType = MFStatusType.MFStatusTypeDeleted; conditionDeleted.TypedValue.SetValue(MFDataType.MFDatatypeBoolean, false); scs.Add(-1, conditionDeleted); var sResults = vault.ObjectSearchOperations.SearchForObjectsByConditionsEx(scs, MFSearchFlags.MFSearchFlagNone, false, 0, 0); return(sResults.GetAsObjectVersions()); }
/// <summary> /// Searches for objects matching the search conditions, in segments by M-Files Object Id. /// Returns an enumerable of each segment's search results. /// Using this approach (e.g. searching for IDs 1-1000, then 1001-2000, etc.) bypasses the return count limitations. /// </summary> /// <param name="vaultObjectSearchOperations">The search operations object to query with.</param> /// <param name="searchConditions">The search conditions to execute.</param> /// <param name="searchFlags">Any search flags to execute (note that the order will not be respected).</param> /// <param name="startSegment">The (zero-based) index of the segment to start at.</param> /// <param name="itemsPerSegment">The number of items to include in each segment. See <see cref="DefaultNumberOfItemsInSegment"/>.</param> /// <param name="maximumSegmentIndex"></param> /// <returns></returns> /// <remarks>Be aware that calling this method will return all matching items, which may cause significant load on the M-Files server.</remarks> public static IEnumerable <IObjectSearchResults> SearchForObjectsByConditionsSegmented(this IVaultObjectSearchOperations vaultObjectSearchOperations, SearchConditions searchConditions, MFSearchFlags searchFlags = MFSearchFlags.MFSearchFlagDisableRelevancyRanking, int startSegment = 0, int itemsPerSegment = IVaultObjectSearchOperationsExtensionMethods.DefaultNumberOfItemsInSegment, int maximumSegmentIndex = IVaultObjectSearchOperationsExtensionMethods.MaximumSegmentIndex) { // Sanity. if (null == searchConditions) { throw new ArgumentNullException(nameof(searchConditions)); } if (null == vaultObjectSearchOperations) { throw new ArgumentNullException(nameof(vaultObjectSearchOperations)); } if (startSegment < 0) { startSegment = IVaultObjectSearchOperationsExtensionMethods.DefaultNumberOfItemsInSegment; } if (maximumSegmentIndex < 0) { maximumSegmentIndex = IVaultObjectSearchOperationsExtensionMethods.MaximumSegmentIndex; } // No point having relevancy ranking as we're throwing it away. // ReSharper disable once BitwiseOperatorOnEnumWithoutFlags searchFlags = searchFlags | MFSearchFlags.MFSearchFlagDisableRelevancyRanking; // A segment has a start index and a number of items in it. // Segment 0 = object Ids 0 through 999. // Segment 1 = object Ids 1000 through 1999. // .... // Start at segment zero. int segment = startSegment; // Let's have a sanity counter, just in case. int sanity = maximumSegmentIndex; // While there are objects with a higher ID than the segment we're in, continue searching. while ((sanity > 0) && vaultObjectSearchOperations.HasMoreResults(searchConditions, segment, searchFlags, itemsPerSegment)) { // Clone the search conditions (so we can add current-segment condition). var internalSearchConditions = searchConditions.Clone(); // Add search condition: // Id within the range: (segment - itemsPerSegment) to ((segment + 1) * itemsPerSegment) internalSearchConditions.AddObjectIdSegmentSearchCondition(segment, itemsPerSegment); // Return the results. yield return(vaultObjectSearchOperations .SearchForObjectsByConditionsEx(internalSearchConditions, searchFlags, SortResults: false, MaxResultCount: 0, SearchTimeoutInSeconds: 0)); // Move to the next segment. segment++; // Reduce the sanity value (if we hit zero we will exit). sanity--; } }
/// <summary> /// Executes a segmented search using the API directly. /// </summary> static void UseApiDirectly() { // Connect to the server (localhost, tcp, current Windows user). var application = new MFilesServerApplication(); application.ConnectAdministrative(); // Get a connection to the vault. var vault = application.LogInToVault(Program.sampleVaultGuid.ToString("B")); // Load the object types from the vault. Console.WriteLine("Loading object types..."); var objectTypes = vault .ObjectTypeOperations .GetObjectTypes() .Cast <ObjType>() .ToList(); Console.WriteLine($"Iterating over {objectTypes.Count} object types..."); // Iterate over the object types to count the objects. foreach (var objectType in objectTypes) { // Create the basic search conditions collection. var searchConditions = new SearchConditions(); // Add a condition for the object type we're interested in. { // Create the search condition (for object type id). SearchCondition condition = new SearchCondition { ConditionType = MFConditionType.MFConditionTypeEqual }; condition.Expression.SetStatusValueExpression(MFStatusType.MFStatusTypeObjectTypeID, null); condition.TypedValue.SetValue(MFDataType.MFDatatypeLookup, objectType.ID); // Add the condition at the index provided. searchConditions.Add(-1, condition); } // Create variables for the segment information. const int itemsPerSegment = 1000; // Maximum number of items in each segment. var segment = 0; // Start; this will increment as we go. var moreItems = true; // Whether there are more items to load. var countIncludingDeleted = 0; // The count of matching items. // Whilst there are items in the results, we need to loop. while (moreItems) { // Execute a search within the object id segment. { // Clone the search conditions (so we can add current-segment condition). var internalSearchConditions = searchConditions.Clone(); // Add search condition: // Id within the range: (segment - itemsPerSegment) to ((segment + 1) * itemsPerSegment) { // Create the search condition. SearchCondition condition = new SearchCondition { ConditionType = MFConditionType.MFConditionTypeEqual }; condition.Expression.SetObjectIDSegmentExpression(itemsPerSegment); condition.TypedValue.SetValue(MFDataType.MFDatatypeInteger, segment); // Add the condition at the index provided. internalSearchConditions.Add(-1, condition); } // Execute the search and increment the count. countIncludingDeleted += vault.ObjectSearchOperations .SearchForObjectsByConditionsEx(internalSearchConditions, MFSearchFlags.MFSearchFlagDisableRelevancyRanking, SortResults: false, MaxResultCount: 0, SearchTimeoutInSeconds: 0).Count; // Move to the next segment. segment++; } // Are there any more items? { // Clone the search conditions (so we can add object id condition). var internalSearchConditions = searchConditions.Clone(); // Add search condition: // Id at least (segment * itemsPerSegment) { // Create the search condition. SearchCondition condition = new SearchCondition { ConditionType = MFConditionType.MFConditionTypeGreaterThanOrEqual }; condition.Expression.SetStatusValueExpression(MFStatusType.MFStatusTypeObjectID, null); condition.TypedValue.SetValue(MFDataType.MFDatatypeInteger, segment * itemsPerSegment); // Add the condition at the index provided. internalSearchConditions.Add(-1, condition); } // If we get one item then there's more results. moreItems = 1 == vault.ObjectSearchOperations.SearchForObjectsByConditionsEx( internalSearchConditions, // Our search conditions. MFSearchFlags.MFSearchFlagDisableRelevancyRanking, SortResults: false, // Don't bother attempting to sort them. MaxResultCount: 1, // We only need to know if there is at least one, nothing more. SearchTimeoutInSeconds: 0).Count; } } // Output the stats. Console.WriteLine($"\t{objectType.NamePlural}:"); Console.WriteLine($"\t\tTotal: {countIncludingDeleted} (included deleted)"); } Console.WriteLine($"Complete."); // Disconnect. vault.LogOutSilent(); application.Disconnect(); }