1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
import freebase, freebase.schema
from freebase.api import LITERAL_TYPE_IDS, MetawebError
from copy import deepcopy
import itertools
import logging
ALL_LINKS_QUERY = [{"type": "/type/link",
"source": {"id" : None},
"target": {"id" : None},
"target_value": None,
"master_property": { "id" : None, "expected_type" : None, "unique" : None },
"operation": None,
"valid": True }]
def merge(s, amoeba_id, target_id):
# In merging, we'll use the analogy of phagocytosis.
# http://en.wikipedia.org/wiki/Phagocytosis
# In this example, the amoeba is the main guy who is swallowing the target
# In cases where there is no merging problem, it doesn't matter who is the
# amoeba and who is the target, but the final merge product will be in the amoeba
# this merging will be done using links
# effectively, we want to move everything that links to the target
# and link it to the amoeba. This does present some issues:
# some things just can't be moved (/en keys, for example).
target_source_l, target_target_l, target_target_v_l = get_all_links(target_id)
amoeba_source_l, amoeba_target_l, amoeba_target_v_l = get_all_links(amoeba_id)
total_delete_query = {}
total_write_query = { "id" : amoeba_id }
# let's redirect all source and target links on target to amoeba
#print [i for i in target_source_l]; print
for link in target_source_l:
# try this
if link.master_property.expected_type != "/type/text" and \
link.master_property.expected_type != "/type/key" and \
link.master_property.id != "/type/object/permission" and \
(not (link.master_property.unique and exists(amoeba_source_l, amoeba_target_l, link.master_property.id))):
prop = link.master_property.id
print prop
current_prop = total_write_query.get(prop, [])
current_prop.append({"id" : link.target.id, "connect" : "replace"})
total_write_query[prop] = current_prop
to_delete_prop = total_delete_query.get(prop, [])
to_delete_prop.append({"id" : link.target.id, "connect" : "delete"})
total_delete_query[prop] = to_delete_prop
for link in target_target_l:
if link.master_property.expected_type != "/type/text" and \
link.master_property.expected_type != "/type/key" and \
link.master_property.id != "/type/object/permission":
prop = "!" + link.master_property.id
print prop
current_prop = total_write_query.get(prop, [])
current_prop.append({"id" : link.source.id, "connect" : "replace"})
total_write_query[prop] = current_prop
to_delete_prop = total_delete_query.get(prop, [])
to_delete_prop.append({"id" : link.source.id, "connect" : "delete"})
total_delete_query[prop] = to_delete_prop
# delete old
badpropnames = set([])
for propname, guys in total_delete_query.iteritems():
new = dict({propname:guys, "id":target_id})
try:
s.mqlwrite(new)
except MetawebError, me:
print "Oh well, %s failed. %s" % (propname, me)
badpropnames.add(propname)
for badprop in badpropnames:
del total_write_query[badprop]
s.mqlwrite(total_write_query)
def exists(source_links, target_links, property_id):
print "testing", property_id
for link in itertools.chain(source_links, target_links):
if link.master_property.id == property_id:
if link.target and link.source:
print "outta here", property_id
return True
return False
return False
def get_all_links(the_id):
source, target, target_value = [deepcopy(ALL_LINKS_QUERY) for i in range(3)]
source[0].update(source={"id" : the_id})
target[0].update(target={"id" : the_id})
target_value[0].update(target_value={"id" : the_id })
return (s.mqlreaditer(source),
s.mqlreaditer(target),
s.mqlreaditer(target_value))
if __name__ == '__main__':
s = freebase.api.HTTPMetawebSession("http://sandbox-freebase.com")
merge(s, "/guid/9202a8c04000641f800000000bc3141d", "/guid/9202a8c04000641f800000000aa5533e")
|