// Remove removes an item into the items collection and remove any // corresponding quads from the graph database. func Remove(context interface{}, db *db.DB, graph *cayley.Handle, itemID string) error { log.Dev(context, "Remove", "Started : ID[%s]", itemID) // Get the item from the items collection. items, err := item.GetByIDs(context, db, []string{itemID}) if err != nil { log.Error(context, "Remove", err, "Completed") return err } // Prepare the item map data. itmMap := map[string]interface{}{ "item_id": items[0].ID, "type": items[0].Type, "version": items[0].Version, "data": items[0].Data, } // Remove the corresponding relationships from the graph. if err := wire.RemoveFromGraph(context, db, graph, itmMap); err != nil { log.Error(context, "Remove", err, "Completed") return err } // Delete the item. if err := item.Delete(context, db, itemID); err != nil { log.Error(context, "Remove", err, "Completed") return err } log.Dev(context, "Remove", "Completed") return nil }
// Import imports an item into the items collections and into the graph database. func Import(context interface{}, db *db.DB, graph *cayley.Handle, itm *item.Item) error { log.Dev(context, "Import", "Started : ID[%s]", itm.ID) // If the item exists and is different than the provided item, // we need to remove existing relationships. if itm.ID != "" { // Get the item if it exists. itmOrig, err := item.GetByID(context, db, itm.ID) if err != nil { if err != item.ErrNotFound { log.Error(context, "Import", err, "Completed") return err } } // If the item exits, we need to determine if the item is the // same as the original. If not, we need to update the // relationships. if itmOrig.ID != "" { // If the item is identical, we don't have to do anything. if reflect.DeepEqual(itmOrig, itm) { log.Dev(context, "Import", "Completed") return nil } // If the item is not identical, remove the stale relationships by // preparing an item map. itmMap := map[string]interface{}{ "item_id": itmOrig.ID, "type": itmOrig.Type, "version": itmOrig.Version, "data": itmOrig.Data, } // Remove the corresponding relationships from the graph. if err := wire.RemoveFromGraph(context, db, graph, itmMap); err != nil { log.Error(context, "Import", err, "Completed") return err } } } // Add the item to the items collection. if err := item.Upsert(context, db, itm); err != nil { log.Error(context, "Import", err, "Completed") return err } // Prepare the generic item data map. itmMap := map[string]interface{}{ "item_id": itm.ID, "type": itm.Type, "version": itm.Version, "data": itm.Data, } // Infer relationships and add them to the graph. if err := wire.AddToGraph(context, db, graph, itmMap); err != nil { log.Error(context, "Import", err, "Completed") return err } log.Dev(context, "Import", "Completed") return nil }
// TestAddRemoveGraph tests if we can add/remove relationship quads to/from cayley. func TestAddRemoveGraph(t *testing.T) { db, store, items := setupGraph(t) defer tests.DisplayLog() t.Log("Given the need to add/remove relationship quads from the Cayley graph.") { t.Log("\tWhen starting from an empty graph") { //---------------------------------------------------------------------- // Infer and add the relationships to the graph. if err := wire.AddToGraph(tests.Context, db, store, items[0]); err != nil { t.Fatalf("\t%s\tShould be able to add relationships to the graph : %s", tests.Failed, err) } t.Logf("\t%s\tShould be able to add relationships to the graph.", tests.Success) //---------------------------------------------------------------------- // Get the relationship quads from the graph. p := cayley.StartPath(store, quad.String("WTEST_80aa936a-f618-4234-a7be-df59a14cf8de")).Out(quad.String("WTEST_flagged")) it, _ := p.BuildIterator().Optimize() defer it.Close() var count int for it.Next() { count++ token := it.Result() value := store.NameOf(token) if quad.NativeOf(value) != "WTEST_d1dfa366-d2f7-4a4a-a64f-af89d4c97d82" { t.Fatalf("\t%s\tShould be able to get the relationships from the graph", tests.Failed) } } if err := it.Err(); err != nil { t.Fatalf("\t%s\tShould be able to get the relationships from the graph : %s", tests.Failed, err) } it.Close() p = cayley.StartPath(store, quad.String("WTEST_d1dfa366-d2f7-4a4a-a64f-af89d4c97d82")).Out(quad.String("WTEST_on")) it, _ = p.BuildIterator().Optimize() defer it.Close() for it.Next() { count++ token := it.Result() value := store.NameOf(token) if quad.NativeOf(value) != "WTEST_c1b2bbfe-af9f-4903-8777-bd47c4d5b20a" { t.Fatalf("\t%s\tShould be able to get the relationships from the graph", tests.Failed) } } if err := it.Err(); err != nil { t.Fatalf("\t%s\tShould be able to get the relationships from the graph : %s", tests.Failed, err) } it.Close() if count != 2 { t.Fatalf("\t%s\tShould be able to get relationships from the graph", tests.Failed) } t.Logf("\t%s\tShould be able to get relationships from the graph.", tests.Success) //---------------------------------------------------------------------- // Try to infer and add the relationships again. if err := wire.AddToGraph(tests.Context, db, store, items[0]); err != nil { t.Fatalf("\t%s\tShould be able to add an item again and maintain relationships : %s", tests.Failed, err) } t.Logf("\t%s\tShould be able to add an item again and maintain relationships.", tests.Success) //---------------------------------------------------------------------- // Remove the relationships from the graph. if err := wire.RemoveFromGraph(tests.Context, db, store, items[0]); err != nil { t.Fatalf("\t%s\tShould be able to remove relationships from the graph : %s", tests.Failed, err) } t.Logf("\t%s\tShould be able to remove relationships from the graph.", tests.Success) //---------------------------------------------------------------------- // Try to get the relationships. count = 0 p = cayley.StartPath(store, quad.String("WTEST_80aa936a-f618-4234-a7be-df59a14cf8de")).Out(quad.String("WTEST_authored")) it, _ = p.BuildIterator().Optimize() defer it.Close() for it.Next() { count++ } if err := it.Err(); err != nil { t.Fatalf("\t%s\tShould be able to verify the empty graph : %s", tests.Failed, err) } it.Close() p = cayley.StartPath(store, quad.String("WTEST_d1dfa366-d2f7-4a4a-a64f-af89d4c97d82")).Out(quad.String("WTEST_on")) it, _ = p.BuildIterator().Optimize() defer it.Close() for it.Next() { count++ } if err := it.Err(); err != nil { t.Fatalf("\t%s\tShould be able to verify the empty graph : %s", tests.Failed, err) } it.Close() if count != 0 { t.Fatalf("\t%s\tShould be able to verify the empty graph", tests.Failed) } t.Logf("\t%s\tShould be able to verify the empty graph.", tests.Success) } } }