Example #1
0
        public List <VertexField> GetVerticesByIds(HashSet <string> vertexId, GraphViewCommand command, string partition,
                                                   bool constructEdges = false)
        {
            const string NODE_ALIAS = "node";
            var          jsonQuery  = new JsonQuery
            {
                NodeAlias      = NODE_ALIAS,
                RawWhereClause = new WBooleanComparisonExpression
                {
                    ComparisonType = BooleanComparisonType.Equals,
                    FirstExpr      = new WColumnReferenceExpression(NODE_ALIAS, DocumentDBKeywords.KW_EDGEDOC_IDENTIFIER),
                    SecondExpr     = new WValueExpression("null")
                }
            };

            // SELECT node
            jsonQuery.AddSelectElement(NODE_ALIAS);
            jsonQuery.FlatProperties.Add(DocumentDBKeywords.KW_EDGEDOC_IDENTIFIER);

            jsonQuery.WhereConjunction(new WInPredicate(
                                           new WColumnReferenceExpression(NODE_ALIAS, GremlinKeyword.NodeID),
                                           vertexId.ToList()), BooleanBinaryExpressionType.And);

            if (partition != null)
            {
                jsonQuery.WhereConjunction(new WBooleanComparisonExpression
                {
                    ComparisonType = BooleanComparisonType.Equals,
                    FirstExpr      = new WValueExpression($"{NODE_ALIAS}{command.Connection.GetPartitionPathIndexer()}", false),
                    SecondExpr     = new WValueExpression(partition, true)
                }, BooleanBinaryExpressionType.And);
            }

            jsonQuery.NodeProperties = new List <string> {
                "node", "*"
            };
            jsonQuery.EdgeProperties = new List <string>();

            IEnumerator <Tuple <VertexField, RawRecord> > queryResult = this.GetVerticesAndEdgesViaVertices(jsonQuery, command);

            List <VertexField> result = new List <VertexField>();

            while (queryResult.MoveNext())
            {
                VertexField vertex = queryResult.Current.Item1;
                result.Add(vertex);
            }

            if (constructEdges)
            {
                // TODO: need double check on JsonServer
                EdgeDocumentHelper.ConstructLazyAdjacencyList(command, EdgeType.Both, vertexId, new HashSet <string>());
            }

            return(result);
        }
Example #2
0
        public IEnumerator <Tuple <VertexField, RawRecord> > GetVerticesAndEdgesViaVertices(JsonQuery vertexQuery,
                                                                                            GraphViewCommand command)
        {
            IEnumerable <JObject> items          = this.ExecuteQueryScript(vertexQuery);
            List <string>         nodeProperties = new List <string>(vertexQuery.NodeProperties);
            List <string>         edgeProperties = new List <string>(vertexQuery.EdgeProperties);

            string nodeAlias = nodeProperties[0];

            // Skip i = 0, which is the (node.* as nodeAlias) field
            nodeProperties.RemoveAt(0);

            //
            // TODO: Refactor
            //
            string edgeAlias    = null;
            bool   isReverseAdj = false;
            bool   isStartVertexTheOriginVertex = false;
            bool   crossApplyEdgeOnServer       = edgeProperties.Any();

            if (crossApplyEdgeOnServer)
            {
                edgeAlias    = edgeProperties[0];
                isReverseAdj = bool.Parse(edgeProperties[1]);
                isStartVertexTheOriginVertex = bool.Parse(edgeProperties[2]);
                edgeProperties.RemoveAt(0);
                edgeProperties.RemoveAt(0);
                edgeProperties.RemoveAt(0);
            }

            //
            // Batch strategy:
            //  - For "small" vertexes, they have been cross applied on the server side
            //  - For "large" vertexes, just return the VertexField, the adjacency list decoder will
            //    construct spilled adjacency lists in batch mode and cross apply edges after that
            //
            Func <VertexField, string, Tuple <VertexField, RawRecord> > makeCrossAppliedRecord = (vertexField, edgeId) => {
                Debug.Assert(vertexField != null);

                RawRecord nodeRecord = new RawRecord();
                //
                // Fill node property field
                //
                foreach (string propertyName in nodeProperties)
                {
                    FieldObject propertyValue = vertexField[propertyName];
                    nodeRecord.Append(propertyValue);
                }

                RawRecord edgeRecord = new RawRecord(edgeProperties.Count);

                EdgeField edgeField =
                    ((AdjacencyListField)vertexField[isReverseAdj ? DocumentDBKeywords.KW_VERTEX_REV_EDGE : DocumentDBKeywords.KW_VERTEX_EDGE])
                    .GetEdgeField(edgeId, true);

                string startVertexId = vertexField.VertexId;
                AdjacencyListDecoder.FillMetaField(edgeRecord, edgeField, startVertexId, vertexField.Partition, isStartVertexTheOriginVertex, isReverseAdj);
                AdjacencyListDecoder.FillPropertyField(edgeRecord, edgeField, edgeProperties);

                nodeRecord.Append(edgeRecord);
                return(new Tuple <VertexField, RawRecord>(vertexField, nodeRecord));
            };

            Func <VertexField, Tuple <VertexField, RawRecord> > makeRawRecord = (vertexField) => {
                Debug.Assert(vertexField != null);

                RawRecord rawRecord = new RawRecord();
                //
                // Fill node property field
                //
                foreach (string propertyName in nodeProperties)
                {
                    FieldObject propertyValue = vertexField[propertyName];
                    rawRecord.Append(propertyValue);
                }
                return(new Tuple <VertexField, RawRecord>(vertexField, rawRecord));
            };

            HashSet <string> uniqueVertexIds = new HashSet <string>();
            HashSet <string> uniqueEdgeIds   = new HashSet <string>();

            foreach (JObject dynamicItem in items)
            {
                JObject tmpVertexObject = (JObject)((JObject)dynamicItem)[nodeAlias];
                string  vertexId        = (string)tmpVertexObject[DocumentDBKeywords.KW_DOC_ID];

                if (crossApplyEdgeOnServer)
                {
                    // Note: since vertex properties can be multi-valued,
                    // a DocumentDB query needs a join clause in the FROM clause
                    // to retrieve vertex property values, which may result in
                    // the same vertex being returned multiple times.
                    // We use the hash set uniqueVertexIds to ensure one vertex is
                    // produced only once.
                    if (EdgeDocumentHelper.IsBuildingTheAdjacencyListLazily(
                            tmpVertexObject,
                            isReverseAdj,
                            this.Connection.UseReverseEdges) &&
                        uniqueVertexIds.Add(vertexId))
                    {
                        VertexField vertexField = command.VertexCache.AddOrUpdateVertexField(vertexId, tmpVertexObject);
                        yield return(makeRawRecord(vertexField));
                    }
                    else // When the DocumentDB query crosses apply edges
                    {
                        JObject edgeObjct = (JObject)((JObject)dynamicItem)[edgeAlias];
                        string  edgeId    = (string)edgeObjct[DocumentDBKeywords.KW_EDGE_ID];

                        if (uniqueEdgeIds.Add(edgeId))
                        {
                            VertexField vertexField = command.VertexCache.AddOrUpdateVertexField(vertexId, tmpVertexObject);
                            yield return(makeCrossAppliedRecord(vertexField, edgeId));
                        }
                    }
                }
                else
                {
                    if (!uniqueVertexIds.Add(vertexId))
                    {
                        continue;
                    }
                    VertexField vertexField = command.VertexCache.AddOrUpdateVertexField(vertexId, tmpVertexObject);
                    yield return(makeRawRecord(vertexField));
                }
            }
        }