Beispiel #1
0
        internal static void AssertGraphsEqual(PropertyGraphModel expected, PropertyGraphModel actual)
        {
            var left  = (JObject)JsonConvert.DeserializeObject(JsonConvention.SerializeObject(SortGraph(expected)));
            var right = (JObject)JsonConvert.DeserializeObject(JsonConvention.SerializeObject(SortGraph(actual)));

            Sort(left); Sort(right);
            Assert.AreEqual(left.ToString(Formatting.None), right.ToString(Formatting.None));
            //Assert.AreEqual(JsonConvention.SerializeObject(SortGraph(expected)), JsonConvention.SerializeObject(SortGraph(actual)));
        }
Beispiel #2
0
        public async override Task Execute(SaveVertexCommand cmd)
        {
            var vertexProps = await UnitOfWork.Db.VertexProperties.Where(
                p => p.VertexId == cmd.VertexId && p.Deleted == null).ToListAsync();

            foreach (var propModel in cmd.Props)
            {
                // close old value if present
                var prop = vertexProps.FirstOrDefault(p => p.SchemaUri == propModel.SchemaUri);

                // serialize value to json
                var jsonValue = JsonConvention.SerializeObject(propModel.Value);

                if (prop != null)
                {
                    if (prop.JsonValue == jsonValue)
                    {
                        // nothing to update
                        continue;
                    }
                    else
                    {
                        // different value - close old property and continue
                        prop.Deleted = _clock.TimeStamp;
                    }
                }

                // if value is null do not add anything
                if (propModel.Value == null)
                {
                    continue;
                }

                // create property
                var newProp = new VertexProperty()
                {
                    Id        = Guid.NewGuid(),
                    VertexId  = cmd.VertexId,
                    SchemaUri = propModel.SchemaUri,
                    Created   = _clock.TimeStamp,
                    JsonValue = jsonValue
                };
                UnitOfWork.Db.VertexProperties.Add(newProp);

                // prevent inserting duplicates
                vertexProps.Add(newProp);
            }

            await Events.OnNext(new SaveVertexCompletedEvent()
            {
                Command = cmd
            });
        }
Beispiel #3
0
        public static HashSet <object> AsSet(this object value)
        {
            var str = value.ToString();

            if (str.StartsWith("[") && str.EndsWith("]"))
            {
                return(JsonConvention.DeserializeObject <HashSet <object> >(str));
            }
            return(new HashSet <object>()
            {
                value
            });
        }
Beispiel #4
0
        /// <summary>
        /// Assumes layout has been already applied
        /// Note: method mutates graph and graphLayout
        /// </summary>
        public void ImproveAppliedLayout(SigmaGraphModel graph, GraphLayout graphLayout, LayoutSettings layoutSettings, TimeSpan duration)
        {
            using (var engine = new V8ScriptEngine())
            {
                try
                {
                    var v8Graph = new V8GraphModel();
                    v8Graph.LoadSigma(graph);
                    engine.AddHostObject("log", _log);

                    engine.Execute("var graph = " + JsonConvention.SerializeObject(v8Graph) + ";");
                    engine.Execute("var settings = " + JsonConvention.SerializeObject(layoutSettings) + ";");
                    engine.Execute("var duration = " + JsonConvention.SerializeObject(duration.TotalMilliseconds) + ";");

                    var baseDirectory = AppDomain.CurrentDomain.BaseDirectory;

                    var forceAtlas2   = engine.Compile(File.ReadAllText($@"{baseDirectory}\App\Graph\Layout\ForceAtlas2.js"));
                    var serviceScript = engine.Compile(File.ReadAllText($@"{baseDirectory}\App\Graph\Layout\GraphLayoutService.js"));
                    engine.Execute(forceAtlas2);
                    engine.Execute(serviceScript);

                    var nodesJson = engine.Evaluate("JSON.stringify(nodes)").ToString();
                    var nodes     = JsonConvention.DeserializeObject <V8NodeModel[]>(nodesJson);
                    for (int i = 0; i < nodes.Length; i++)
                    {
                        var node = graph.Nodes[i];
                        node.X = nodes[i].x;
                        node.Y = nodes[i].y;

                        var id = node.Entity;
                        if (id.HasValue)
                        {
                            graphLayout[id.Value] = new GraphLayout.Coords()
                            {
                                X = nodes[i].x,
                                Y = nodes[i].y
                            };
                        }
                    }
                }
                catch (ScriptEngineException e)
                {
                    _log.Error("V8 exception: " + e.ErrorDetails);
                    throw;
                }
            }
        }
        public async override Task Execute(CreateVertexCommand cmd)
        {
            UnitOfWork.Db.Vertices.Add(new Vertex()
            {
                Id        = cmd.VertexId,
                NetworkId = cmd.NetworkId,
                Created   = _clock.TimeStamp
            });

            if (cmd.Props != null)
            {
                foreach (var propModel in cmd.Props)
                {
                    // serialize value to json
                    var jsonValue = JsonConvention.SerializeObject(propModel.Value);

                    // if value is null do not add anything
                    if (propModel.Value == null)
                    {
                        continue;
                    }

                    // create property
                    var newProp = new VertexProperty()
                    {
                        Id        = Guid.NewGuid(),
                        VertexId  = cmd.VertexId,
                        SchemaUri = propModel.SchemaUri,
                        Created   = _clock.TimeStamp,
                        JsonValue = jsonValue
                    };
                    UnitOfWork.Db.VertexProperties.Add(newProp);
                }
            }

            await Events.OnNext(new SaveVertexCompletedEvent()
            {
                Command = new SaveVertexCommand()
                {
                    VertexId = cmd.VertexId,
                    Props    = cmd.Props
                }
            });
        }
Beispiel #6
0
 internal static void AssertGraphsEqual(string expected, string actual)
 {
     AssertGraphsEqual(JsonConvention.DeserializeObject <PropertyGraphModel>(expected), JsonConvention.DeserializeObject <PropertyGraphModel>(actual));
 }
Beispiel #7
0
        public async override Task Execute(SaveEdgeCommand cmd)
        {
            // is the relationship already there?
            var edge = await UnitOfWork.Db.Edges.Where(
                e => e.SourceVertexId == cmd.SourceVertexId && e.TargetVertexId == cmd.TargetVertexId &&
                e.SchemaUri == cmd.SchemaUri &&
                e.Deleted == null).FirstOrDefaultAsync();

            var edgeExists = (edge != null);

            if (!edgeExists)
            {
                // relationship not found - create edge
                edge = new Entities.Edge()
                {
                    Id             = Guid.NewGuid(),
                    SourceVertexId = cmd.SourceVertexId,
                    TargetVertexId = cmd.TargetVertexId,
                    SchemaUri      = cmd.SchemaUri,
                    Created        = _clock.TimeStamp,
                };
                UnitOfWork.Db.Edges.Add(edge);
            }

            if (cmd.Props != null)
            {
                var edgeProps = await UnitOfWork.Db.EdgeProperties.Where(
                    p => p.EdgeId == edge.Id && p.Deleted == null)
                                .ToListAsync();

                foreach (var propModel in cmd.Props)
                {
                    var jsonValue = JsonConvention.SerializeObject(propModel.Value);

                    if (edgeExists)
                    {
                        // relationship found - find if the proeprty isn't already there
                        var prop = edgeProps.SingleOrDefault(p => p.SchemaUri == propModel.SchemaUri);

                        if (prop != null)
                        {
                            if (prop.JsonValue == jsonValue)
                            {
                                // nothing to update
                                continue;
                            }
                            else
                            {
                                // different value - close old property and continue
                                prop.Deleted = _clock.TimeStamp;
                            }
                        }
                    }

                    // if value is null do not add anything
                    if (propModel.Value == null)
                    {
                        continue;
                    }

                    // create property
                    var newProp = new EdgeProperty()
                    {
                        Id        = Guid.NewGuid(),
                        EdgeId    = edge.Id,
                        SchemaUri = propModel.SchemaUri,
                        Created   = _clock.TimeStamp,
                        JsonValue = jsonValue
                    };
                    UnitOfWork.Db.EdgeProperties.Add(newProp);

                    // prevent inserting duplicate props
                    edgeProps.Add(newProp);
                }
            }

            await Events.OnNext(new SaveEdgeCompletedEvent()
            {
                Command = cmd
            });
        }
Beispiel #8
0
        public override async Task <List <DuplicateResult> > Execute(DuplicatesQuery query)
        {
            var graph = (await _queryService.Execute(new InternalGraphQuery()
            {
                NetworkId = query.NetworkId
            }, this))
                        .Snapshot();
            var settings = await _queryService.Execute(new NetworkSettingsQuery()
            {
                NetworkId = query.NetworkId
            }, this);

            var requiredProps = settings.Invitations.RequiredProps;

            var duplicatesByRequiredProps =
                graph.Vertices.Select(
                    v => new {
                Key    = string.Join("::", requiredProps.Select(prop => v.Props.ContainsKey(prop) ? JsonConvention.SerializeObject(v.Props[prop]) : "")),
                Vertex = v
            })
                .GroupBy(g => g.Key)
                .Where(g => g.Count(v => true) > 1)
                .Select(g => new Duplicate()
            {
                Score    = 1,
                Key      = g.Select(a => a.Vertex.Id).OrderBy(id => id).ToArray(),
                Vertices = g.Select(a => a.Vertex)
            });

            var labelProp = settings.ProfileCard.LabelProp;

            var duplicatesByLabel =
                graph.Vertices.Select(
                    v => new {
                Label  = v.Props.ContainsKey(labelProp) ? v.Props[labelProp].ToString().ToLowerInvariant().Trim() : "",
                Vertex = v
            })
                .GroupBy(g => g.Label)
                .Where(g => g.Count(v => true) > 1)
                .Select(g => new Duplicate()
            {
                Score    = 0.5,
                Key      = g.Select(a => a.Vertex.Id).OrderBy(id => id).ToArray(),
                Vertices = g.Select(a => a.Vertex)
            });

            var duplicates = duplicatesByRequiredProps.ToDictionary(d => d.Key, d => d, new ArrayEqualityComparer());

            foreach (var duplicate in duplicatesByLabel)
            {
                if (!duplicates.ContainsKey(duplicate.Key))
                {
                    duplicates[duplicate.Key] = duplicate;
                }
            }

            var accounts = await
                               (from account in _repo.Db.Accounts
                               join user in _repo.Db.Users on account.ApplicationUserId equals user.Id
                               join vertex in _repo.Db.Vertices on account.VertexId equals vertex.Id
                               where vertex.NetworkId == query.NetworkId
                               group new { user.Email, account.InvitationDate } by vertex.Id into g
                               select new
            {
                VertexId = g.Key,
                Accounts = g.ToList()
            }
                               ).ToDictionaryAsync(g => g.VertexId, g => g.Accounts.OrderBy(a => a.InvitationDate));

            var result = new List <DuplicateResult>();

            foreach (var duplicate in duplicates.Values.OrderByDescending(d => d.Score))
            {
                foreach (var vertex in duplicate.Vertices)
                {
                    vertex.Props = vertex.Props.ToProfileCardProps(settings.ProfileCard);
                    if (accounts.ContainsKey(vertex.Id))
                    {
                        vertex.Props["Account email"] = accounts[vertex.Id].First().Email;
                    }
                }
                var firstAccountVertex = duplicate.Vertices.Select(v => new
                {
                    Vertex         = v,
                    InvitationDate =
                        accounts.ContainsKey(v.Id) ? accounts[v.Id].First().InvitationDate : DateTime.MaxValue
                }).OrderBy(a => a.InvitationDate).First();
                result.Add(new DuplicateResult()
                {
                    Vertex     = firstAccountVertex.Vertex,
                    Duplicates = duplicate.Vertices.Where(v => v != firstAccountVertex.Vertex).ToList()
                });
            }

            return(result);
        }
Beispiel #9
0
        public Dictionary <Tuple <Guid, Guid, string>, ConcurrentEdgeModel> GenerateConcurrentEdgeModel(GraphSchemaModel schema, InternalGraphEdgesResult edges)
        {
            //
            var uriNameDictionary = schema.EdgeSchema.ToDictionary(e => e.Uri, e => e.Name);

            // source, target, edgeName, propName => timestamp
            var propTimestamps = new Dictionary <Tuple <Guid, Guid, string, string>, DateTime>();

            // edges
            var edgesResult = new Dictionary <Tuple <Guid, Guid, string>, ConcurrentEdgeModel>();

            foreach (var relationshipSchema in schema.EdgeSchema)
            {
                // możliwe jest wiele relacji do różnych węzłów (a każda może mieć wiele propsów)
                Dictionary <Tuple <Guid, Guid>, InternalGraphEdgesResult.InternalEdgeModel> edgeBucket;
                if (!edges.Edges.TryGetValue(relationshipSchema.Uri, out edgeBucket))
                {
                    continue;
                }

                foreach (var edge in edgeBucket)
                {
                    var edgeKey = new Tuple <Guid, Guid, string>(edge.Key.Item1, edge.Key.Item2, uriNameDictionary[relationshipSchema.Uri]);
                    // find model
                    ConcurrentEdgeModel edgeModel;
                    if (!edgesResult.TryGetValue(edgeKey, out edgeModel))
                    {
                        edgeModel = new ConcurrentEdgeModel()
                        {
                            Id             = edge.Value.Id,
                            SourceVertexId = edge.Value.SourceId,
                            TargetVertexId = edge.Value.TargetId,
                            Name           = relationshipSchema.Name,
                            Props          = new ConcurrentDictionary <string, object>(StringComparer.OrdinalIgnoreCase)
                        };
                        edgesResult.Add(edgeKey, edgeModel);
                    }

                    if (relationshipSchema.PropsSchema != null)
                    {
                        foreach (var propSchema in relationshipSchema.PropsSchema)
                        {
                            if (!edge.Value.PropsJson.ContainsKey(propSchema.Uri))
                            {
                                continue;
                            }
                            if (edgeModel.Props.ContainsKey(propSchema.Name))
                            {
                                continue;
                            }

                            var prop = edge.Value.PropsJson[propSchema.Uri];
                            if (!edgeModel.Props.ContainsKey(propSchema.Name))
                            {
                                var value = JsonConvention.DeserializeObject(prop.JsonValue);
                                edgeModel.Props.TryAdd(propSchema.Name, value);
                            }
                            else
                            {
                                // check timestamp for update (newer props override older)
                                var timestampKey = new Tuple <Guid, Guid, string, string>(edgeModel.SourceVertexId,
                                                                                          edgeModel.TargetVertexId, edgeModel.Name, propSchema.Name);
                                var timestamp = propTimestamps[timestampKey];
                                if (timestamp < prop.TimeStamp)
                                {
                                    var value = JsonConvention.DeserializeObject(prop.JsonValue);
                                    edgeModel.Props.TryAdd(propSchema.Name, value);
                                }
                            }
                        }
                    }
                }
            }
            return(edgesResult);
        }
Beispiel #10
0
        public Dictionary <Guid, ConcurrentVertexModel> GenerateConcurrentVertexModel(GraphSchemaModel schema, InternalGraphVerticesResult vertices)
        {
            var vertexIdPropNameTimeStamp = new Dictionary <Tuple <Guid, String>, DateTime>(new TupeGuidStringComparer());
            var verticesResult            = new Dictionary <Guid, ConcurrentVertexModel>();
            var processedPropUris         = new HashSet <string>();

            foreach (var sectionSchema in schema.VertexSchema)
            {
                if (sectionSchema.PropsSchema != null)
                {
                    foreach (var propSchema in sectionSchema.PropsSchema)
                    {
                        List <InternalGraphVerticesResult.InternalVertexPropModel> propsBucket;
                        if (!vertices.WithProps.TryGetValue(propSchema.Uri, out propsBucket))
                        {
                            continue;
                        }

                        processedPropUris.Add(propSchema.Uri);
                        foreach (var prop in propsBucket)
                        {
                            ConcurrentVertexModel vertex;
                            if (!verticesResult.TryGetValue(prop.VertexId, out vertex))
                            {
                                vertex = new ConcurrentVertexModel()
                                {
                                    Id    = prop.VertexId,
                                    Props = new ConcurrentDictionary <string, object>(StringComparer.OrdinalIgnoreCase)
                                };
                                verticesResult.Add(prop.VertexId, vertex);
                            }

                            if (!vertex.Props.ContainsKey(propSchema.Name))
                            {
                                var value = JsonConvention.DeserializeObject(prop.JsonValue);
                                vertex.Props.TryAdd(propSchema.Name, value);
                                vertexIdPropNameTimeStamp.Add(new Tuple <Guid, string>(vertex.Id, propSchema.Name),
                                                              prop.TimeStamp);
                            }
                            else
                            {
                                // should we override the value?
                                DateTime lastTimeStamp =
                                    vertexIdPropNameTimeStamp[new Tuple <Guid, string>(vertex.Id, propSchema.Name)];
                                if (lastTimeStamp < prop.TimeStamp)
                                {
                                    var value = JsonConvention.DeserializeObject(prop.JsonValue);
                                    vertex.Props[propSchema.Name] = value;
                                }
                            }
                        }
                    }
                }
            }

            // handle props outside schema
            var outsideSchema = vertices.WithProps.Where(v => !processedPropUris.Contains(v.Key));

            foreach (var propsBucket in outsideSchema)
            {
                var name = propsBucket.Key.Split('/').Last();
                foreach (var prop in propsBucket.Value)
                {
                    ConcurrentVertexModel vertex;
                    if (!verticesResult.TryGetValue(prop.VertexId, out vertex))
                    {
                        vertex = new ConcurrentVertexModel()
                        {
                            Id    = prop.VertexId,
                            Props = new ConcurrentDictionary <string, object>(StringComparer.OrdinalIgnoreCase)
                        };
                        verticesResult.Add(prop.VertexId, vertex);
                    }

                    if (!vertex.Props.ContainsKey(name))
                    {
                        var value = JsonConvention.DeserializeObject(prop.JsonValue);
                        vertex.Props.TryAdd(name, value);
                        vertexIdPropNameTimeStamp.Add(new Tuple <Guid, string>(vertex.Id, name),
                                                      prop.TimeStamp);
                    }
                    else
                    {
                        // should we override the value?
                        DateTime lastTimeStamp =
                            vertexIdPropNameTimeStamp[new Tuple <Guid, string>(vertex.Id, name)];
                        if (lastTimeStamp < prop.TimeStamp)
                        {
                            var value = JsonConvention.DeserializeObject(prop.JsonValue);
                            vertex.Props[name] = value;
                        }
                    }
                }
            }

            // vertices witour props
            foreach (var withoutProp in vertices.WithoutProps)
            {
                verticesResult.Add(withoutProp, new ConcurrentVertexModel()
                {
                    Id    = withoutProp,
                    Props = new ConcurrentDictionary <string, object>(StringComparer.OrdinalIgnoreCase)
                });
            }
            return(verticesResult);
        }