def overall_suggestions_user_count(): with NeoGraph() as graph: cursor = graph.run(''' MATCH (v:Video)-[w:WAS_SUGGESTED]->(u:SocialUser) RETURN COUNT(DISTINCT u) as count ''') return _parse_count(cursor.data())
def user_watches(): with NeoGraph() as graph: cursor = graph.run(''' MATCH (u:SocialUser) OPTIONAL MATCH (u)-[ww:WATCHED]->(vw:Video) WHERE ww.progress > 0 WITH u, COUNT(DISTINCT vw) as watch_count OPTIONAL MATCH (u)-[wd:WATCHED]->(vd:Video) RETURN u, watch_count, COUNT(DISTINCT vd) as dismiss_count ORDER BY watch_count DESC, dismiss_count DESC ''') stats = [ { 'socialuser': SocialUser.wrap(d['u']), 'watch_count': d['watch_count'], 'dismiss_count': d['dismiss_count'], # 'completed_surveys': Survey.objects.filter(completed_by=SocialUser.wrap(d['u']).user_id).count(), } for d in cursor.data() ] user_ids = set([stat['socialuser'].user_id for stat in stats]) completed_surveys_per_user = { user.id: user.survey_count for user in User.objects.filter(id__in=user_ids).annotate( survey_count=Count('completed_surveys')) } for stat in stats: stat['completed_surveys'] = completed_surveys_per_user.get( stat['socialuser'].user_id, 0) return stats
def get_context_data(self, **kwargs): context = super(SocialUserUpdateView, self).get_context_data(**kwargs) with NeoGraph() as graph: pk = int(self.kwargs.get(self.pk_url_kwarg)) obj = SocialUser.select(graph, pk).first() context['user_id'] = obj.user_id return context
def watch_and_history(self, video_name, history_videos): with NeoGraph() as graph: obj = Video.select(graph).where( '_.name = "{}"'.format(video_name)).first() response = self.client.post( reverse('api:watch_videos'), json.dumps({ 'data': { 'type': 'watches', 'attributes': { 'video_id': obj.id, 'date': datetime.now().isoformat(), 'rating': 1, 'progress': 1, } } }), content_type='application/vnd.api+json', ) self.assertEqual(response.status_code, 204) response = self.client.get(reverse('api:history')) self.assertEqual(response.status_code, 200) self.assertJSONDataVideoNames(response, history_videos, test_dependency_count=False)
def overall_dismiss_user_count(): with NeoGraph() as graph: cursor = graph.run(''' MATCH (v:Video)<-[w:WATCHED]-(u:SocialUser) WHERE w.progress = 0 RETURN COUNT(DISTINCT u) as count ''') return _parse_count(cursor.data())
def user_for_django_user(cls, dj_id): with NeoGraph() as graph: obj = cls.select(graph).where( '_.user_id = {}'.format(dj_id)).first() if obj is None: raise Http404( _('No %(verbose_name)s found matching the query') % {'verbose_name': cls.__name__}) return obj
def check_objects(self, pk1, pk2): with NeoGraph() as graph: a = get_neo_object_or_404(self.get_start_model(), int(pk1), graph).node b = get_neo_object_or_404(self.get_end_model(), int(pk2), graph).node rel = get_neo_relationship_or_404(a, self.get_relationship_name(), b, graph) return a, rel, b
def create_neo_socialuser(user_id): user = SocialUser() with NeoGraph() as graph: tx = graph.begin() user.id = tx.run('MATCH (n:{}) RETURN COUNT(n)+1'.format( SocialUser.__primarylabel__)).evaluate() user.user_id = user_id tx.create(user) tx.commit()
def setUp(self): token = Token.objects.first() self.client.defaults['HTTP_AUTHORIZATION'] = 'Token ' + token.key # Delete SocialUser object that is created by the Djangos post_save signal. # We need the node created by us because we want to create some relationships. with NeoGraph() as graph: graph.run( 'MATCH (a:SocialUser) WHERE NOT (a)-[:HAS_PREFERENCE]->() DELETE a' )
def suggestions_user_count(): with NeoGraph() as graph: cursor = graph.run(''' MATCH (v:Video)-[w:WAS_SUGGESTED]->(u:SocialUser) RETURN v, COUNT(w) as suggestion_count, COUNT(DISTINCT u) as user_count ORDER BY suggestion_count DESC, user_count DESC ''') return [{ 'video': Video.wrap(d['v']), 'suggestion_count': d['suggestion_count'], 'user_count': d['user_count'], } for d in cursor.data()]
def watch_user_count(): with NeoGraph() as graph: cursor = graph.run(''' MATCH (v:Video)<-[w:WATCHED]-(u:SocialUser) WHERE w.progress > 0 RETURN v, COUNT(w) as watch_count, COUNT(DISTINCT u) as user_count ORDER BY watch_count DESC, user_count DESC ''') return [{ 'video': Video.wrap(d['v']), 'watch_count': d['watch_count'], 'user_count': d['user_count'], } for d in cursor.data()]
def post(self, request, pk1, pk2, *args, **kwargs): a, rel, b = self.check_objects(pk1, pk2) valid = self.validate_post_data(request.POST, rel) messages = {} if valid: with NeoGraph() as graph: for key in rel: rel[key] = request.POST[key] graph.push(rel) messages.update({'success': ['Relationship updated']}) else: messages.update({'error': ['Saving failed: Invalid data']}) context = self.create_context_data(a, rel, b) context.update({'messages': messages}) return render(request, self.template_name, context)
def watch_history(cls, user_id): with NeoGraph() as graph: cursor = graph.run( ''' MATCH (u:SocialUser{user_id:{user_id}})-[w:WATCHED]->(v:Video) WHERE w.progress > 0 RETURN DISTINCT v, MAX(w.date) as date, COUNT(w) as count, MAX(w.progress) as progress ORDER BY date DESC ''', { 'user_id': user_id, }) data = [(Video.wrap(d['v']), d['date'], d['count'], d['progress']) for d in cursor.data()] videos = [d[0] for d in data] context = {d[0].id: d[1:] for d in data} return videos, context
def next_videos_preferences(cls, user_id, limit=1): with NeoGraph() as graph: cursor = graph.run( ''' MATCH (u:SocialUser{user_id:{user_id}}) OPTIONAL MATCH (u)-[hasWatched:WATCHED]->(videosW:Video) WHERE hasWatched.progress > 0 WITH COLLECT(DISTINCT videosW) as videosWatched MATCH (u:SocialUser{user_id:{user_id}}) OPTIONAL MATCH (u)-[hasDismissed:WATCHED]->(videosSkiped:Video) WHERE hasDismissed.progress = 0 AND hasDismissed.date STARTS WITH {today} WITH videosWatched, COLLECT(DISTINCT videosSkiped) as videosSkipedToday MATCH (v1:Video)-[:REQUIRES_VIDEO|REQUIRES_GROUP|CONTAINS*0..]->(v2:Video) WITH v1, videosWatched, videosSkipedToday, none(x in COLLECT(DISTINCT v2) WHERE NOT x in videosWatched AND v1 <> x) as deps WHERE deps AND NOT v1 in videosWatched AND NOT v1 in videosSkipedToday MATCH (u:SocialUser{user_id:{user_id}}) OPTIONAL MATCH (cat:Category) OPTIONAL MATCH (u)-[pref:HAS_PREFERENCE]->(cat) OPTIONAL MATCH (u)-[w:WATCHED]->(v:Video)-[b:BELONGS_TO]->(cat) WHERE w.rating >= 0 WITH v1, cat, toFloat(coalesce(max(pref.weight), 0.5)) as prefw, toFloat(coalesce(AVG(toFloat(w.rating) * toFloat(b.weight)), 1)) as ratew WITH v1, cat, prefw * ratew as catWeight OPTIONAL MATCH (v1)-[belongs:BELONGS_TO]->(cat) WITH v1, toFloat(AVG(coalesce(belongs.weight, 0.1) * catWeight)) as weight OPTIONAL MATCH (v3:Video)-[:REQUIRES_VIDEO]->(v1) RETURN v1, weight, COUNT(DISTINCT v3) as dep_count ORDER BY weight DESC, tostring(v1.name) LIMIT {limit} ''', { 'user_id': user_id, 'today': datetime.now().isoformat() [:10], # returns date with format 'YYYY-MM-DD' 'limit': limit, }) data = [(Video.wrap(d['v1']), d['weight'], d['dep_count']) for d in cursor.data()] videos = [d[0] for d in data] context = { d[0].id: { 'weigth': d[1], 'dep_count': d[2], } for d in data } return videos, context
def watch_count(cls, user_id): with NeoGraph() as graph: cursor = graph.run( ''' MATCH (u:SocialUser{user_id:{user_id}})-[w:WATCHED]->(v:Video) WHERE w.progress > 0 RETURN COUNT(DISTINCT v) as count ''', { 'user_id': user_id, }) data = cursor.data() if not isinstance(data, list): return 0 if len(data) == 0: return 0 count = data[0].get('count') if not isinstance(count, int): return 0 return count
def test_post_watch_video_missing_progress(self): with NeoGraph() as graph: obj = Video.select(graph).where( '_.name = "{}"'.format('A')).first() response = self.client.post( reverse('api:watch_videos'), json.dumps({ 'data': { 'type': 'watches', 'attributes': { 'video_id': obj.id, 'date': datetime.now().isoformat(), 'rating': 1, } } }), content_type='application/vnd.api+json', ) self.assertEqual(response.status_code, 400)
def handle(self, *fixture_paths, **options): self.verbosity = options['verbosity'] for path in fixture_paths: object_map = dict() relationship_count = 0 with open(os.path.join(settings.BASE_DIR, path), 'r') as fixture_file: data = json.load(fixture_file) nodes = data.get('nodes', []) relationships = data.get('relationships', []) # create objects with properties for node_entry in nodes: model_class = _model_class(node_entry) obj = model_class() obj.id = node_entry['id'] for name, value in node_entry['attributes'].items(): setattr(obj, name, value) object_map[_key_for_node(node_entry)] = obj # create relationship between objects for rel_entry in relationships: start_obj = object_map[_key_for_node(rel_entry['start'])] end_obj = object_map[_key_for_node(rel_entry['end'])] selection, to_obj = _find_selection( start_obj, end_obj, rel_entry['type']) selection.add(to_obj, rel_entry['attributes']) relationship_count += 1 with NeoGraph() as graph: for obj in object_map.values(): graph.create(obj) if self.verbosity >= 1: self.stdout.write( '{path}: {obj_count} objects and {rel_count} relationships created' .format( **{ 'path': path, 'obj_count': len(object_map), 'rel_count': relationship_count, }))
def dismiss_and_survey(self, video_name, survey_link): with NeoGraph() as graph: obj = Video.select(graph).where( '_.name = "{}"'.format(video_name)).first() response = self.client.post( reverse('api:watch_videos'), json.dumps({ 'data': { 'type': 'watches', 'attributes': { 'video_id': obj.id, 'date': datetime.now().isoformat(), 'rating': -1, 'progress': 0, } } }), content_type='application/vnd.api+json', ) self.assertEqual(response.status_code, 204) response = self.client.get(reverse('api:survey_latest')) self.assertEqual(response.status_code, 200) self.assertJSONDataSurveyLink(response, survey_link)
def _post_teardown(self): super(NeoTestCase, self)._post_teardown() if self.neo_fixtures: with NeoGraph() as graph: graph.run('MATCH (a)-[r]->(b) DELETE a, r, b') graph.run('MATCH (a) DELETE a')