public void UpdateNode(SearchExpressionNode ex) { if (!TryGetNode(ex, out var node)) { return; } node.title = FormatTitle(ex); if (ex.color != Color.clear) { node.titleContainer.style.backgroundColor = ex.color; } // Update result port if (ex.type == ExpressionType.Value || ex.type == ExpressionType.Provider) { var outputPort = FindPort(node, "output"); if (outputPort != null) { outputPort.portName = Convert.ToString(ex.value); } } else if (ex.type == ExpressionType.Union) { UpdateUnionVariables(node); } else if (ex.type == ExpressionType.Select) { var outputPort = FindPort(node, "output"); if (outputPort != null) { outputPort.portName = GetSelectNodeOutputPortName(ex); } } else if (ex.type == ExpressionType.Map) { if (ex.TryGetVariableSource(ExpressionKeyName.X, out var xSource)) { if (!ex.TryGetProperty(ExpressionKeyName.GroupBy, out string groupBy) || string.IsNullOrEmpty(groupBy)) { ex.SetProperty(ExpressionKeyName.GroupBy, GetSelectNodeOutputPortName(xSource).ToLowerInvariant()); } } if (ex.TryGetVariableSource(ExpressionKeyName.Y, out var ySource) && xSource == ySource) { ex.SetProperty(nameof(Mapping), (int)Mapping.Table); } } NotifyGraphChanged(); }
private void DrawMapEditor() { var mapping = (Mapping)m_Node.GetProperty(nameof(Mapping), (int)Mapping.Count); var groupBy = m_Node.GetProperty(ExpressionKeyName.GroupBy, ""); EditorGUI.BeginChangeCheck(); mapping = (Mapping)EditorGUILayout.EnumPopup(nameof(Mapping), mapping); if (m_Node.TryGetVariableSource(ExpressionKeyName.X, out var xSource) && xSource != null && mapping != Mapping.Table) { groupBy = EditorGUILayout.DelayedTextField("Group By", groupBy); } else { GUILayout.Space(20); } if (EditorGUI.EndChangeCheck()) { m_Node.SetProperty(nameof(Mapping), (int)mapping); m_Node.SetProperty(ExpressionKeyName.GroupBy, groupBy); propertiesChanged?.Invoke(m_Node); } }
private SearchRequest BuildTwoSetRequest(SearchExpressionNode ex, Func <IList <SearchItem>, IList <SearchItem>, IEnumerable <SearchItem> > transformer) { if (ex.variables == null) { return(null); } var exSearch = new SearchRequest(ex.type); if (ex.source != null && ex.TryGetVariableSource("With", out var withSource) && withSource != null) { var sourceExpression = BuildRequest(ex.source); var withExpression = BuildRequest(withSource); exSearch.DependsOn(sourceExpression); exSearch.DependsOn(withExpression); bool fetchSourceItemsFinished = false; bool fetchWithItemsFinished = false; var sourceItems = new List <SearchItem>(); var withItems = new List <SearchItem>(); sourceExpression.Resolve(results => sourceItems.AddRange(results), exs => fetchSourceItemsFinished = true); withExpression.Resolve(results => withItems.AddRange(results), exs => fetchWithItemsFinished = true); exSearch.resolved += exs => { if (fetchSourceItemsFinished && fetchWithItemsFinished) { exSearch.ProcessItems(null, transformer(sourceItems, withItems)); } }; } return(exSearch); }
private SearchRequest BuildMappingRequest(SearchExpressionNode node) { var mapping = (Mapping)node.GetProperty(nameof(Mapping), (int)Mapping.Count); var groupBy = node.GetProperty(ExpressionKeyName.GroupBy, ""); if (node.TryGetVariableSource(ExpressionKeyName.X, out var xSource) && String.IsNullOrWhiteSpace(groupBy)) { Debug.LogWarning($"Group by {mapping} mapping not defined for {node.name ?? node.id}."); return(SearchRequest.empty); } var grouping = xSource != null; if (!node.TryGetVariableSource(ExpressionKeyName.Y, out var ySource)) { Debug.LogWarning($"No data source (Y) set for {node.name ?? node.id}."); return(SearchRequest.empty); } else if (grouping && ySource.type == ExpressionType.Select && !ySource.GetProperty(ExpressionKeyName.Mapped, false)) { Debug.LogWarning($"Mapping data source for {node.name ?? node.id} must be a search node (currently a {ySource.type} node)"); if (ySource.source?.type == ExpressionType.Search) { ySource = ySource.source; } } var mappingRequest = new SearchRequest(node.type); if (mapping == Mapping.Table) { if (xSource == null) { Debug.LogWarning($"No data source (X) set for {node.name ?? node.id}."); return(SearchRequest.empty); } var xRequest = BuildRequest(xSource); var yRequest = BuildRequest(ySource); mappingRequest.DependsOn(xRequest); mappingRequest.DependsOn(yRequest); bool fetchSourceX = false; var xItems = new List <SearchItem>(); xRequest.Resolve(results => xItems.AddRange(results), exs => fetchSourceX = true); bool fetchSourceY = false; var yItems = new List <SearchItem>(); yRequest.Resolve(results => yItems.AddRange(results), exs => fetchSourceY = true); mappingRequest.resolved += _ => { if (!fetchSourceX || !fetchSourceY) { throw new ExpressionException(node, "Table mapping wasn't resolved properly"); } int xIndex = 0; foreach (var x in xItems) { var y = yItems.Count >= 0 && xIndex < yItems.Count ? yItems[xIndex].value : null; if (y != null && !(y is double) && double.TryParse(y.ToString(), out var d)) { y = d; } x.value = new MappingData() { type = Mapping.Table, value = y, query = xSource.GetProperty(ExpressionKeyName.BakedQuery, x.context?.searchQuery) }; x.description = $"{y}"; ++xIndex; } mappingRequest.ProcessItems(xItems); }; } else { var groupsRequest = BuildRequest(xSource ?? new SearchExpressionNode(ExpressionType.Value, null, "")); var groups = new Dictionary <string, List <object> >(); mappingRequest.DependsOn(groupsRequest); groupsRequest.Resolve(items => { foreach (var item in items) { var groupName = grouping ? item.id : node.name ?? mapping.ToString(); var groupQuery = grouping ? $"({ySource.value}) {groupBy}={groupName}" : ySource.value as string; var groupSource = grouping ? new SearchExpressionNode(ySource.type, ySource.source, groupQuery, ySource.variables) : ySource; var groupRequest = BuildRequest(groupSource); mappingRequest.DependsOn(groupRequest); groupsRequest.DependsOn(groupRequest); if (!groups.ContainsKey(groupName)) { groups[groupName] = new List <object>(); } var groupData = groups[groupName]; var totalCount = 0.0; var totalValue = 0.0; groupRequest.Resolve(groupItems => { switch (mapping) { case Mapping.Min: UpdateMappingMin(groupData, groupItems); break; case Mapping.Max: UpdateMappingMax(groupData, groupItems); break; case Mapping.Average: UpdateMappingAverage(groupData, groupItems, ref totalCount, ref totalValue); break; case Mapping.Count: UpdateMappingCount(groupData, groupItems); break; } }, _ => { mappingRequest.ProcessItems(groupData.OrderBy(e => e).Select(e => new SearchItem(xSource == null ? e?.ToString() : groupName) { score = double.TryParse(groupName, out var d) ? -(int)d : groupName.GetHashCode(), label = groupName, description = e?.ToString(), value = new MappingData() { type = mapping, value = e, query = groupSource.GetProperty(ExpressionKeyName.BakedQuery, groupQuery) } })); }); } }, null);