func getFrequencyRelations(db *neoism.Database, r *model.Relationship, t *testing.T) int { res := []struct { Frequency int `json:"frequency"` }{} cq := neoism.CypherQuery{ Statement: fmt.Sprintf( ` MATCH (subject:%[1]s)-[r:%[2]s]->(object:%[3]s) WHERE subject.id = {subjectId} AND object.id = {objectId} RETURN r.frequency as frequency `, util.UpperCaseFirst(r.Subject), strings.ToUpper(r.Relationship), util.UpperCaseFirst(r.Object), ), Parameters: neoism.Props{"subjectId": r.SubjectID, "objectId": r.ObjectID}, Result: &res, } if err := db.Cypher(&cq); err != nil { assert.Fail(t, "Unexpected error: "+err.Error()) return -1 } if len(res) > 0 { return res[0].Frequency } return -1 }
// Check if reference to a person associated with that room. // If it is, create a "REFERENCED" edge between speaker and // the reference. If that edge already exists, increment // the "times" property by 1. func messaged(msg *irc.Message, DB *neoism.Database) { message := msg.Trailing for name, _ := range users { if strings.Contains(message, name) { speaker := cleanName(msg.Prefix.Name) reference := name fmt.Printf("%v was referenced by %v\n", speaker, reference) statement := fmt.Sprintf( `MERGE (s:User {name: "%v"}) MERGE (u:User {name: "%v"}) MERGE (s)-[r:REFERENCED]->(u) ON MATCH SET r.times = coalesce(r.times, 0) + 1`, speaker, reference) query := neoism.CypherQuery{ Statement: statement, } err := DB.Cypher(&query) if err != nil { fmt.Println(err) } } } }
func InsertUID(conn *neoism.Database, key *puck_gpg.PrimaryKey, uid *puck_gpg.UserID) { kid := key.KeyID() app.Logger.Debugf("Inserting UID %s of %s", uid.Keywords, kid) parsed := parseUID(uid.Keywords) cq0 := neoism.CypherQuery{ Statement: ` MATCH (k:Key {keyid: {keyid}}) MERGE k-[r:HasID]-(i:UserID { keyword: {keyword}, uuid: {uuid}, name: {name}, comment: {comment}, email: {email}, domain: {domain} })`, Parameters: neoism.Props{ "keyid": key.KeyID(), "keyword": uid.Keywords, "uuid": uid.UUID, "name": parsed.name, "comment": parsed.comment, "email": parsed.email, "domain": parsed.domain, }, } err := conn.Cypher(&cq0) if err != nil { panic(err) } }
// Create user node and "IS_IN" edge to room if non-existent. func joined(msg *irc.Message, DB *neoism.Database) { room := msg.Params[0] user := cleanName(msg.Prefix.Name) if users[user] == nil { users[user] = []string{room} } contains := false for _, r := range users[user] { if r == room { contains = true break } } if contains != true { users[user] = append(users[user], room) statement := fmt.Sprintf( `MERGE (n:Room {name: "%v"}) MERGE (u:User {name: "%v"}) MERGE (n)<-[:IS_IN]-(u)`, room, user) // Create new room node if non-existent query := neoism.CypherQuery{ Statement: statement, } err := DB.Cypher(&query) if err != nil { fmt.Println(err) } } }
/* GetTags returns collection of news */ func GetTags(db *neoism.Database) (*[]Tag, error) { var tags []Tag if err := db.Cypher(&neoism.CypherQuery{ Statement: `MATCH (tag:Tag) RETURN DISTINCT ID(tag) as id, tag.name as name`, Result: &tags, }); err != nil { return nil, err } return &tags, nil }
/* GetNewsProviders returns collection of news */ func GetNewsProviders(db *neoism.Database) (*[]NewsProvider, error) { var newsproviders []NewsProvider if err := db.Cypher(&neoism.CypherQuery{ Statement: `MATCH (newsprovider:NewsProvider) RETURN DISTINCT ID(newsprovider) as id, newsprovider.name as name`, Result: &newsproviders, }); err != nil { return nil, err } return &newsproviders, nil }
func doQueries(conn *neoism.Database, queries []string) { for _, s := range queries { q := neoism.CypherQuery{ Statement: s, } err := conn.Cypher(&q) if err != nil { panic(err) } } }
/* GetLocations returns collection of news */ func GetLocations(db *neoism.Database) (*[]Location, error) { var locations []Location if err := db.Cypher(&neoism.CypherQuery{ Statement: `MATCH (location:Location) RETURN DISTINCT ID(location) as id, location.name as name`, Result: &locations, }); err != nil { return nil, err } return &locations, nil }
/* GetPeople returns collection of news */ func GetPeople(db *neoism.Database) (*[]Person, error) { var people []Person if err := db.Cypher(&neoism.CypherQuery{ Statement: `MATCH (person:Person) RETURN DISTINCT ID(person) as id, person.name as name`, Result: &people, }); err != nil { return nil, err } return &people, nil }
/* GetCompanies returns collection of news */ func GetCompanies(db *neoism.Database) (*[]Company, error) { var companies []Company if err := db.Cypher(&neoism.CypherQuery{ Statement: `MATCH (company:Company) RETURN DISTINCT ID(company) as id, company.name as name`, Result: &companies, }); err != nil { return nil, err } return &companies, nil }
// DeleteRelationship deletes a relationship func DeleteRelationship(db *neoism.Database, r *model.Relationship) error { cq := neoism.CypherQuery{ Statement: fmt.Sprintf( ` MATCH (a:%s)-[r:%s]->(b:%s) WHERE a.id = {subjectId} AND b.id = {objectId} DELETE r `, util.UpperCaseFirst(r.Subject), strings.ToUpper(r.Relationship), util.UpperCaseFirst(r.Object), ), Parameters: neoism.Props{ "subjectId": r.SubjectID, "objectId": r.ObjectID, }, } return db.Cypher(&cq) }
func InsertPubKey(conn *neoism.Database, k *puck_gpg.PrimaryKey) { cq0 := neoism.CypherQuery{ Statement: ` MERGE (n:Key {keyid: {keyid}}) ON CREATE SET n.fingerprint = {fingerprint} ON MATCH SET n.fingerprint = {fingerprint};`, Parameters: neoism.Props{ "keyid": k.KeyID(), "fingerprint": k.Fingerprint()}} err := conn.Cypher(&cq0) if err != nil { panic(err) } }
/* GetNewsItem returns the new with that id */ func GetNewsItem(db *neoism.Database, id int) (*NewsItem, error) { var news []NewsItem if err := db.Cypher(&neoism.CypherQuery{ Statement: `MATCH (new:NewsItem)<-[r]-(k:NewsProvider) WHERE ID(new) = {id} RETURN DISTINCT ID(new) as id, new.title as title, new.url as url,new.image as image, new.body as body, new.language as language, k.name as source`, Parameters: neoism.Props{"id": id}, Result: &news, }); err != nil { return nil, err } else if len(news) == 0 { return nil, errors.New("not found") } else { return &news[0], nil } }
// CreateOrIncRelationship creates a relationship or increments a property if it // already exists func CreateOrIncRelationship(db *neoism.Database, r *model.Relationship) error { cq := neoism.CypherQuery{ Statement: fmt.Sprintf( ` MATCH (a:%s), (b:%s) WHERE a.id = {subjectId} AND b.id = {objectId} CREATE UNIQUE (a)-[r:%s]->(b) SET r.frequency = COALESCE(r.frequency, 0) + 1 `, util.UpperCaseFirst(r.Subject), util.UpperCaseFirst(r.Object), strings.ToUpper(r.Relationship), ), Parameters: neoism.Props{ "subjectId": r.SubjectID, "objectId": r.ObjectID, }, } return db.Cypher(&cq) }
func cypher(db *neoism.Database) { cq := neoism.CypherQuery{ Statement: ` START n=node(*) MATCH (n)-[r:outranks]->(m) WHERE n.shirt = {color} RETURN n.name, type(r), m.name `, Parameters: neoism.Props{"color": "blue"}, Result: &[]struct { N string `json:"n.name"` Rel string `json:"type(r)"` M string `json:"m.name"` }{}, } // db.Session.Log = true db.Cypher(&cq) fmt.Println(cq.Result) // &[{Spock outranks McCoy} {Spock outranks Scottie} {McCoy outranks Scottie}] }
func getOrCreateNode(db *neoism.Database, label string, key string, value string, props neoism.Props) *neoism.Node { res := []struct { // `json:` tags matches column names in query N neoism.Node }{} //MATCH (n:Tag { name: 'deporte' }) RETURN n st := "MATCH (n:" + label + " { " + key + ": '" + value + "' }) RETURN n" println(st) cq0 := neoism.CypherQuery{ // Use backticks for long statements - Cypher is whitespace indifferent Statement: st, Parameters: neoism.Props{}, Result: &res, } db.Cypher(&cq0) // println("largo") // println(len(res)) // tagName, err := n1.Property("name") // println(tagName) // println(err) var node *neoism.Node if len(res) > 0 { // existe el tag println("si") node = &res[0].N node.Db = db } else { println("no") node, _ = db.CreateNode(props) node.AddLabel(label) } return node }
// Adds nodes for users who were already in the room before // spectator was started. If they were added from another // room, they are not added. An edge is drawn to show that // they are in the room. func inchan(msg *irc.Message, DB *neoism.Database) { nicks := strings.Split(msg.Trailing, " ") room := msg.Params[2] queryStart := fmt.Sprintf(`MERGE (n:Room {name: "%v"}) `, room) rawQuery := []string{queryStart} for i, u := range nicks { cu := cleanName(u) if users[u] == nil { pattern := fmt.Sprintf(`MERGE (u%v:User {name: "%v"}) MERGE (u%v)-[:IS_IN]->(n)`, i, cu, i) rawQuery = append(rawQuery, pattern) } } query := neoism.CypherQuery{ Statement: strings.Join(rawQuery, " "), } err := DB.Cypher(&query) if err != nil { fmt.Println(err) } }
/* Insert a signature in to the database. */ func InsertSignature(conn *neoism.Database, pubkey *puck_gpg.PrimaryKey, uid *puck_gpg.UserID, sig *puck_gpg.Signature) { signerKID := sig.IssuerKeyID() signeeKID := pubkey.KeyID() app.Logger.Debugf("Got Signature by %s on %s", signerKID, signeeKID) // Stub out the signer key, in case it's not yet in the DB q_signer := neoism.CypherQuery{ Statement: `MERGE (n:Key {keyid: {kid}});`, Parameters: neoism.Props{"kid": signerKID}, } err := conn.Cypher(&q_signer) if err != nil { log.Fatal(err) } //Add the signature record q_signature := neoism.CypherQuery{ Statement: ` MATCH (m:Key {keyid: {signee}})-[ii:HasID]-(i:UserID {uuid: {uuid}}), (n:Key {keyid: {signer}}) MERGE n-[r:SIGNS]->i`, Parameters: neoism.Props{ "uuid": uid.UUID, "signee": signeeKID, "signer": signerKID, }, } err = conn.Cypher(&q_signature) if err != nil { log.Fatal(err) } app.SigCounter.Mark(1) }
func ViewRelationships(db *neoism.Database, w http.ResponseWriter, r *http.Request) { log.Print(r.URL.Query().Get("url")) // get nodes from database concerning the url requested rawurl, err := url.QueryUnescape(r.URL.Query().Get("url")) if err != nil { http.Error(w, "URL should be escaped.", 400) return } u, err := helpers.ParseURL(rawurl) if err != nil { http.Error(w, "URL is invalid.", 400) return } stdurl := helpers.GetStandardizedURL(u) res := []struct { ANAME string BNAME string AID int BID int RELKIND string RELID int URLS []string }{} cq := neoism.CypherQuery{ Statement: ` MATCH (u:URL)<-[:INSTANCE]-(a) WHERE u.stdurl = {url} OR u.url = {url} MATCH path=(a)-[r:RELATIONSHIP*1..10]-(b) WITH nodes(path) AS nodes UNWIND nodes AS n WITH DISTINCT n AS n MATCH (u)<-[:INSTANCE]-(n) RETURN n.name AS aname, id(n) AS aid, extract(url IN collect(DISTINCT u) | url.stdurl) AS urls, '' AS bname, 0 AS bid, '' AS relkind, 0 AS relid UNION ALL MATCH (u:URL)<-[:INSTANCE]-(a) WHERE u.stdurl = {url} OR u.url = {url} MATCH path=(a)-[r:RELATIONSHIP*1..10]-(b) WITH relationships(path) AS rels UNWIND rels AS r WITH DISTINCT r AS r WITH startnode(r) AS a, endnode(r) AS b, r RETURN a.name AS aname, id(a) AS aid, b.name AS bname, id(b) AS bid, r.kind AS relkind, id(r) AS relid, [] AS urls `, Parameters: neoism.Props{"url": stdurl}, Result: &res, } err = db.Cypher(&cq) if err != nil { log.Print(err) http.Error(w, "An error ocurred", 400) return } // make dot string s := helpers.GenerateDotString(res, r.URL.Query()) log.Print(s) // generate svg graph buffer := helpers.RenderGraph(s) // write the response as image w.Header().Set("Content-Type", "image/svg+xml") if _, err := w.Write(buffer.Bytes()); err != nil { log.Print("unable to write image. ", err) } }
/* GetNewsItems returns collection of news */ func GetNewsItems(db *neoism.Database, tags []string, providers []string, categories []string, people []string, locations []string, companies []string, page int) (*[]NewsItem, error) { var news []NewsItem matchClause := []string{"MATCH (new:NewsItem)<-[r]-(p:NewsProvider)"} matchClause = append(matchClause, un.MapString(func(tag string) string { return fmt.Sprintf("(new:NewsItem)--(:Tag{name: \"%s\"})", strings.TrimSpace(tag)) }, tags)...) matchClause = append(matchClause, un.MapString(func(category string) string { return fmt.Sprintf("(new:NewsItem)--(:Category{name: \"%s\"})", strings.TrimSpace(category)) }, categories)...) // match := strings.Join(append(matchClause, "(new:NewsItem)--(p:NewsProvider)"), ", ") // match := strings.Join(matchClause, ", ") match := strings.Join(append(matchClause, "(new:NewsItem)"), ", ") query := "RETURN DISTINCT ID(new) as id, new.title as title, new.url as url, new.image as image, new.body as body,new.language as language, p.name as source" where := "WHERE NOT new.url = \"\"" if len(providers) != 0 { names := un.MapString(func(provider string) string { return fmt.Sprintf("\"%s\"", strings.TrimSpace(provider)) }, providers) where = where + fmt.Sprintf(" AND p.name in [%s]", strings.Join(names, ", ")) } if len(locations) != 0 { match = match + ", (new:NewsItem)<-[h]-(l:Location)" names := un.MapString(func(location string) string { return fmt.Sprintf("\"%s\"", strings.TrimSpace(location)) }, locations) where = where + fmt.Sprintf(" AND l.name in [%s]", strings.Join(names, ", ")) query = query + ", l.name as location" } if len(companies) != 0 { match = match + ", (new:NewsItem)--(co:Company)" names := un.MapString(func(company string) string { return fmt.Sprintf("\"%s\"", strings.TrimSpace(company)) }, companies) where = where + fmt.Sprintf(" AND co.name in [%s]", strings.Join(names, ", ")) query = query + ", co.name as company" } if len(people) != 0 { match = match + ", (new:NewsItem)--(person:Person)" names := un.MapString(func(person string) string { return fmt.Sprintf("\"%s\"", strings.TrimSpace(person)) }, people) where = where + fmt.Sprintf(" AND person.name in [%s]", strings.Join(names, ", ")) query = query + ", person.name as person" } paging := fmt.Sprintf("SKIP %d LIMIT %d", page*itemsPerPage, itemsPerPage) // fmt.Printf("%s %s %s %s", match, where, query, paging) if err := db.Cypher(&neoism.CypherQuery{ Statement: fmt.Sprintf("%s %s %s %s", match, where, query, paging), Result: &news, }); err != nil { return nil, err } return &news, nil }
func CreateRelationship(db *neoism.Database, w http.ResponseWriter, r *http.Request) { relationship := r.FormValue("rel") if relationship == "" { relationship = "relates" } else { relationship = strings.ToLower(relationship) } source, err := helpers.ParseURL(r.FormValue("source")) if err != nil { http.Error(w, "source is invalid URL: "+r.FormValue("source"), 400) return } target, err := helpers.ParseURL(r.FormValue("target")) if err != nil { http.Error(w, "target is invalid URL: "+r.FormValue("target"), 400) return } sourceTitle, err := helpers.GetTitle(source) if err != nil { http.Error(w, "Couldn't fetch title for "+source.String(), 400) return } targetTitle, err := helpers.GetTitle(target) if err != nil { http.Error(w, "Couldn't fetch title for "+target.String(), 400) return } if helpers.EqualURLs(source, target) { http.Error(w, "URLs are equal.", 400) return } // standardize urls stdsource := helpers.GetStandardizedURL(source) stdtarget := helpers.GetStandardizedURL(target) // get user user := "******" cq := neoism.CypherQuery{ // sn, su, tn, tu = source node, source url, target node, target url Statement: ` MERGE (su:URL {stdurl: {stdsource}}) ON CREATE SET su.title = {sourceTitle} SET su.rawurl = {rawsource} MERGE (tu:URL {stdurl: {stdtarget}}) ON CREATE SET tu.title = {targetTitle} SET su.rawurl = {rawtarget} CREATE UNIQUE (su)<-[:INSTANCE]-(sn:Node) CREATE UNIQUE (tu)<-[:INSTANCE]-(tn:Node) SET sn.name = CASE WHEN sn.name IS NOT NULL THEN sn.name ELSE su.title END SET tn.name = CASE WHEN tn.name IS NOT NULL THEN tn.name ELSE tu.title END MERGE (sn)-[rel:RELATIONSHIP {user: {user}}]->(tn) ON CREATE SET rel.created = {now} SET rel.kind = {relationshipKind} `, Parameters: neoism.Props{ "stdsource": stdsource, "stdtarget": stdtarget, "rawsource": source.String(), "rawtarget": target.String(), "sourceTitle": sourceTitle, "targetTitle": targetTitle, "user": user, "relationshipKind": relationship, "now": time.Now().UTC().Format("20060102150405"), }, } err = db.Cypher(&cq) if err != nil { log.Print(err) http.Error(w, "An error ocurred", 400) return } w.WriteHeader(http.StatusOK) }