-
Notifications
You must be signed in to change notification settings - Fork 2
/
tests.py
205 lines (161 loc) · 9.06 KB
/
tests.py
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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
import os
import unittest
import tempfile
from py2neo import Graph, Node, Relationship
from flask import session
from app.views import getPy2NeoSession
from collections import defaultdict
from pandas import DataFrame, concat
class FlaskrTestCase(unittest.TestCase):
def test_recs(self):
# Insert test users and activities
graph = getPy2NeoSession()
tx = graph.begin()
try:
# Create test users and activities with the following relationships
for i in range(0, 5):
graph.data("CREATE (actvy: Activity {name:{aName}})",
{"aName": "testActivity%d" % i})
for i in range(0, 4):
graph.data("CREATE (u: User {username:{uname}})",
{"uname": "testUser%d" % i})
'''
Initialize the following relationships between each user and activity.
Commit these to the database afterwards
user 0 is connected to activites 0,1
user 1 is connected to activities 0, 1, 2, 3, 4
user 2 is connected to activities 1, 2, 3, 4
user 3 is connected to activities 1, 4
'''
for i in range(0, 2):
tx.run("MATCH (u:User {username:'testUser0'}), (a:Activity {name:{aname}})"
"CREATE (u)-[:HAS_BEEN_TO{weight:1}]->(a)", aname = "testActivity%d" % i)
for i in range(0, 5):
tx.run("MATCH (u:User {username:'testUser1'}), (a:Activity {name:{aname}})"
"CREATE (u)-[:HAS_BEEN_TO{weight:1}]->(a)", aname = "testActivity%d" % i)
for i in range(1, 5):
tx.run("MATCH (u:User {username:'testUser2'}), (a:Activity {name:{aname}})"
"CREATE (u)-[:HAS_BEEN_TO{weight:1}]->(a)", aname = "testActivity%d" % i)
for i in [1,4]:
tx.run("MATCH (u:User {username:'testUser3'}), (a:Activity {name:{aname}})"
"CREATE (u)-[:HAS_BEEN_TO{weight:1}]->(a)", aname = "testActivity%d" % i)
tx.commit()
# Query for all of testUser0's activities
activities = graph.run("MATCH (u:User {username: 'testUser0'} )"
"-[:HAS_BEEN_TO]->(a:Activity) RETURN a").data()
assert len(activities) == 2
# Get all users who rated the same activities as the current user
similarUsers = graph.run("MATCH (u:User {username: 'testUser0'} )"
"-[:HAS_BEEN_TO{weight:1}]->(a:Activity)<-[:HAS_BEEN_TO{weight:1}]-(other:User)"
"WHERE NOT (other.username = 'testUser0') RETURN other.username").data()
# Create a list of the names of users who share at least one
# activity with testUser0
uniqueSimUsers = []
for sim in similarUsers:
for key, value in sim.items():
uniqueSimUsers.append(value)
# Remove duplicates
uniqueSimUsers = set(uniqueSimUsers)
assert len(uniqueSimUsers) == 3
# List of users who meet the cutoff
possibleUserRecs = []
# Compute similarity of all similar users
for simUser in uniqueSimUsers:
# Get number of activities both the current user and user in similarUsers list have rated
sharedActivities = graph.run("MATCH (u:User {username: 'testUser0'} )"
"-[:HAS_BEEN_TO{weight:1}]->(a)<-[:HAS_BEEN_TO{weight:1}]-(sim:User {username:{sUser}})"
" RETURN a", sUser = simUser).data()
# 0.2 is the similarity cutoff
# If the following quotient is greater or equal than 0.2,
# then the similar user's name is added to possibleUserRecs
if (len(sharedActivities) / len(activities) >= 0.2):
possibleUserRecs.append(simUser)
assert len(possibleUserRecs) == 3
# activities will contain the popularity of activities
# that will be recommended to testUser0
activities = defaultdict(lambda: 0)
# Get activities rated by at least two users in possibleRecs but not by the current user
for simUser in possibleUserRecs:
uniqueActivities = graph.data("MATCH (simUser:User {username:{sUser}})"
"-[:HAS_BEEN_TO{weight:1}]->(a) MATCH (u:User {username:'testUser0'})"
"WHERE NOT (u)-[:HAS_BEEN_TO]->(a) RETURN a.name", sUser = simUser)
for a in uniqueActivities:
for key, value in a.items():
activities[value] += 1
assert(activities['testActivity4'] == 3)
assert(activities['testActivity3'] == 2)
assert(activities['testActivity2'] == 2)
assert(activities['testActivity1'] == 0)
assert(activities['testActivity0'] == 0)
# Returns list of sorted (key, value) tuples in descending order according to the the second tuple element
sortedActivities = sorted(activities.items(), key=lambda x: x[1], reverse=True)
assert len(sortedActivities) == 5
assert sortedActivities[0][0] == 'testActivity4'
assert sortedActivities[1][0] == 'testActivity3' or 'testActivity2'
assert sortedActivities[2][0] == 'testActivity3' or 'testActivity2'
finally:
# Delete test nodes and their relationships
for i in range(0, 4):
graph.data("MATCH (u:User {username:{uname}}) DETACH DELETE u", uname = "testUser%d" % i)
for i in range(0, 5):
graph.data("MATCH (a:Activity {name:{aname}}) DETACH DELETE a", aname = "testActivity%d" % i)
#union = graph.data("MATCH (sim:User {username: 'ekimlin'})-[:HAS_BEEN_TO]->(simAct:Activity)"
# "WITH COUNT(simAct) AS numActs, simAct as allActs "
# "MATCH (allActs) "
# "WHERE NOT (:User {username:'stephen'})-[:HAS_BEEN_TO]->(allActs) "
# "RETURN numActs AS FirstPart, allActs.name AS SecondPart")
#"WITH COUNT(simAct) AS numActs, simAct as allActs "
union = graph.data("MATCH (sim:User {username: {suser}})-[:HAS_BEEN_TO]->(simAct:Activity)"
"WITH simAct as allActs "
"MATCH (allActs) "
"WHERE NOT (:User {username:{curr}})-[:HAS_BEEN_TO]->(allActs) "
"RETURN allActs.name as aName", suser = 'ekimlin', curr = 'stephen')
df = DataFrame(union)
#print(df)
#"WITH COUNT(simAct) AS numActs, simAct as allActs "
union2 = graph.data("MATCH (sim:User {username: {suser}})-[:HAS_BEEN_TO]->(simAct:Activity)"
"WITH simAct as allActs "
"MATCH (allActs) "
"WHERE NOT (:User {username:{curr}})-[:HAS_BEEN_TO]->(allActs) "
"RETURN allActs.name as aName", suser = 'ekimlin', curr = 'stephen')
df2 = DataFrame(union2)
print(df2)
print("SIZE OF union2: ", df2.shape[0])
frames = [df, df2]
mergedDf = concat(frames)
#print(mergedDf)
countingDf = DataFrame(mergedDf.groupby('aName').size().rename('counts'))
#print(countingDf)
mostPopularDf = countingDf.nlargest(4, 'counts')
popularList = []
for row in df.itertuples():
pID, count = row
popularList.append(pID)
print("Most popular: ", popularList)
def test_recs_no_relationships(self):
# Insert test users and activities
graph = getPy2NeoSession()
try:
tx = graph.begin()
graph.data("CREATE (u:User {name:'testUser0', trait4:'entertainment',"
"trait2:'art', trait3:'outside', trait1:'food'})")
num = graph.run("MATCH (u:User {username: 'testUser0'} )"
"-[r:HAS_BEEN_TO]->(a) RETURN count(r)").evaluate()
num2 = graph.run("MATCH (u:User {username: 'testUser0'} )"
"-[r:HAS_BEEN_TO]->(a) RETURN count(r)").data()
tx.commit()
# Count the number of currUser's activities
activities = graph.run("MATCH (u:User {username: 'testUser0'} )"
"-[:HAS_BEEN_TO]->(a:Activity) RETURN a").data()
assert(not activities)
mostPopular = graph.run("MATCH (s)-[h:HAS_BEEN_TO]->(a:Activity),"
"(u:User {username:'testUser0'})"
"WHERE a.label = u.trait1 OR a.label = u.trait2 "
"OR a.label = u.trait3 OR a.label = u.trait4 "
"WITH a, COUNT(h) as c "
"ORDER BY c DESC LIMIT 4 "
"RETURN a.placeID")
finally:
graph.data("MATCH (u:User {name:'testUser0'}) DETACH DELETE u")
if __name__ == '__main__':
unittest.main()