Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 55 additions & 5 deletions src/DynamoCore/Search/SearchDictionary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,16 @@ internal SearchDictionary(ILogger logger = null)
this.logger = logger;
}

/// <summary>
/// Dictionary of searchElement:(tag, weight)
/// </summary>
protected readonly Dictionary<V, Dictionary<string, double>> entryDictionary =
new Dictionary<V, Dictionary<string, double>>();

private List<IGrouping<string, Tuple<V, double>>> tagDictionary;
/// <summary>
/// Dictionary of tag:(list(searchelement, weight)) which contains all nodes that share a tag
/// </summary>
private List<IGrouping<string, Tuple<V, double>>> tagDictionary;

/// <summary>
/// All the current entries in search.
Expand Down Expand Up @@ -283,6 +289,29 @@ private static bool MatchWithQueryString(string key, string[] subPatterns)
return (double)numberOfMatchSymbols / numberOfAllSymbols > 0.8;
}

/// <summary>
/// Check if any element in the given subset
/// matches any element in the tagDictionary.
/// </summary>
/// <param name="subset">The subset that will be used to match elements in tagDictionary.</param>
/// <returns></returns>
private static bool MatchWithSubset(IGrouping<string, Tuple<V, double>> pair, IEnumerable<SearchElements.NodeSearchElement> subset)
{
foreach (var eleAndWeight in pair)
{
var currentElement = (eleAndWeight.Item1 as SearchElements.NodeSearchElement).FullName;
foreach (var ele in subset)
{
//if any element in tagDictionary matches to any element in subset, return true
if (currentElement.IndexOf(ele.FullName) != -1)
{
return true;
}
}
}
return false;
}

private static string[] SplitOnWhiteSpace(string s)
{
return s.Split(null);
Expand Down Expand Up @@ -320,11 +349,26 @@ internal void RebuildTagDictionary()
}

/// <summary>
/// Search for elements in the dictionary based on the query
/// Extract subset of nodes from tagDictionary to limit search scope
/// </summary>
/// <param name="subset"> The subset that will be extracted. </param>
private List<IGrouping<string, Tuple<V, double>>> BuildSubsetDictionary(IEnumerable<SearchElements.NodeSearchElement> subset)
{
var subsetDictionary = new List<IGrouping<string, Tuple<V, double>>>();
foreach (var pair in tagDictionary.Where(x => MatchWithSubset(x, subset)))
{
subsetDictionary.Add(pair);
}
return subsetDictionary;
}

/// <summary>
/// Search for elements in the dictionary or subset based on the query
/// </summary>
/// <param name="query"> The query </param>
/// <param name="minResultsForTolerantSearch">Minimum number of results in the original search strategy to justify doing more tolerant search</param>
internal IEnumerable<V> Search(string query, int minResultsForTolerantSearch = 0)
/// <param name="subset">Subset of nodes that should be used for the search instead of the complete set of nodes</param>
internal IEnumerable<V> Search(string query, int minResultsForTolerantSearch = 0, IEnumerable<SearchElements.NodeSearchElement> subset = null)
{
#if DEBUG
Stopwatch stopwatch = null;
Expand All @@ -334,13 +378,13 @@ internal IEnumerable<V> Search(string query, int minResultsForTolerantSearch = 0
stopwatch.Start();
}
#endif

var searchDict = new Dictionary<V, double>();

if (tagDictionary == null)
{
RebuildTagDictionary();
}
var currentDictionary = tagDictionary;

query = query.ToLower();

Expand All @@ -351,7 +395,13 @@ internal IEnumerable<V> Search(string query, int minResultsForTolerantSearch = 0
subPatternsList.Insert(0, query);
subPatterns = (subPatternsList).ToArray();

foreach (var pair in tagDictionary.Where(x => MatchWithQueryString(x.Key, subPatterns)))
//check if subset is provided, if yes then extract the subset from tagDictionary
if (subset != null)
{
currentDictionary = BuildSubsetDictionary(subset);
}

foreach (var pair in currentDictionary.Where(x => MatchWithQueryString(x.Key, subPatterns)))
{
ComputeWeightAndAddToDictionary(query, pair, searchDict);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,20 +106,10 @@ internal void SearchAutoCompleteCandidates(string input)
{
if (PortViewModel == null) return;

var queriedSearchElements = searchElementsCache.Where(e => QuerySearchElements(e, input)).ToList();
//Providing the saved search results to limit the scope of the query search.
var foundNodes = Search(input, searchElementsCache);
FilteredResults = new List<NodeSearchElementViewModel>(foundNodes).OrderBy(x => x.Name).ThenBy(x => x.Description);

FilteredResults = GetViewModelForNodeSearchElements(queriedSearchElements);
}

/// <summary>
/// Returns true if the user input matches the name of the filtered node element.
/// </summary>
/// <returns>True or false</returns>
private bool QuerySearchElements(NodeSearchElement e, string input)
{
StringComparison stringComparison = StringComparison.CurrentCultureIgnoreCase;

return e.Name.IndexOf(input, stringComparison) >= 0;
}

/// <summary>
Expand Down
7 changes: 4 additions & 3 deletions src/DynamoCoreWpf/ViewModels/Search/SearchViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -866,13 +866,14 @@ private void IsSelectedChanged(object sender, PropertyChangedEventArgs e)
}

/// <summary>
/// Performs a search using the given string as query.
/// Performs a search using the given string as query and subset, if provided.
/// </summary>
/// <returns> Returns a list with a maximum MaxNumSearchResults elements.</returns>
/// <param name="search"> The search query </param>
internal IEnumerable<NodeSearchElementViewModel> Search(string search)
/// <param name="subset">Subset of nodes that should be used for the search instead of the complete set of nodes. This is a list of NodeSearchElement types</param>
internal IEnumerable<NodeSearchElementViewModel> Search(string search, IEnumerable<NodeSearchElement> subset = null)
{
var foundNodes = Model.Search(search);
var foundNodes = Model.Search(search, 0, subset);
return foundNodes.Select(MakeNodeSearchElementVM);
}

Expand Down
2 changes: 1 addition & 1 deletion test/DynamoCoreWpfTests/NodeAutoCompleteSearchTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ public void SearchNodeAutocompletionSuggestions()

// Filter the node elements using the search field.
searchViewModel.SearchAutoCompleteCandidates("ar");
Assert.AreEqual(2 , searchViewModel.FilteredResults.Count());
Assert.AreEqual(4 , searchViewModel.FilteredResults.Count());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@zeusongit Looks like the number diff is expected due to?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because the search term ar now returns more than 2 results as the search scope has been increased to cover description and keywords.

}

[Test]
Expand Down