def test_get_top_user_track_tags(app):
    """Tests that top tags for users can be queried"""
    with app.app_context():
        db = get_db()

    test_entities = {
        'tracks': [
            {"tags": ""},
            {},
            {"tags": "pop,rock,electric"},
            {"tags": "pop,rock"},
            {"tags": "funk,pop"},
        ]
    }

    populate_mock_db(db, test_entities)

    with db.scoped_session() as session:
        session.execute("REFRESH MATERIALIZED VIEW tag_track_user")
        user_1_tags = _get_top_user_track_tags(session, {'user_id': 1})
        user_2_tags = _get_top_user_track_tags(session, {'user_id': 2})

    assert len(user_1_tags) == 4
    assert user_1_tags[0] == 'pop'
    assert user_1_tags[1] == 'rock'
    assert 'electric' in user_1_tags
    assert 'funk' in user_1_tags

    assert not user_2_tags
def test_get_tracks_by_date(app):
    """Test getting tracks ordering by date"""
    with app.app_context():
        db = get_db()

    test_entities = {
        'tracks': [
            {
                "track_id": 1,
                "owner_id": 1287289,
                "release_date": "Fri Dec 20 2019 12:00:00 GMT-0800",
                "created_at": datetime(2018, 5, 17)
            },
            {
                "track_id": 2,
                "owner_id": 1287289,
                "created_at": datetime(2018, 5, 18)
            },
            {
                "track_id": 3,
                "owner_id": 1287289,
                "release_date": "Wed Dec 18 2019 12:00:00 GMT-0800",
                "created_at": datetime(2020, 5, 17)
            },
            {
                "track_id": 4,
                "owner_id": 1287289,
                "release_date": "",
                "created_at": datetime(2018, 5, 19)
            },
            {
                "track_id": 5,
                "owner_id": 1287289,
                "release_date": "garbage-should-not-parse",
                "created_at": datetime(2018, 5, 20)
            },
        ],
    }

    populate_mock_db(db, test_entities)

    with db.scoped_session() as session:
        tracks = _get_tracks(session, {
            "user_id": 1287289,
            "offset": 0,
            "limit": 10,
            "sort": "date"
        })

        assert len(tracks) == 5
        assert tracks[0]["track_id"] == 1
        assert tracks[1]["track_id"] == 3
        assert tracks[2]["track_id"] == 5
        assert tracks[3]["track_id"] == 4
        assert tracks[4]["track_id"] == 2
Exemple #3
0
def test_search_user_tags(app):
    """Tests that search by tags works for users"""
    with app.app_context():
        db = get_db()

    test_entities = {
        'tracks': [
            {"track_id": 1, "tags": "pop", "owner_id": 1},
            {"track_id": 2, "owner_id": 1, "tags": "pop,rock,electric"},
            {"track_id": 3, "owner_id": 2},
            {"track_id": 4, "owner_id": 2, "tags": "funk,pop"},
            {"track_id": 5, "owner_id": 2, "tags": "funk,pop"},
            {"track_id": 6, "owner_id": 2, "tags": "funk,Funk,kpop"},
            {"track_id": 7, "owner_id": 3, "tags": "pop"},
            {"track_id": 8, "owner_id": 3, "tags": "kpop"}
        ],
        'users': [
            {'user_id': 1, 'handle': '1'},
            {'user_id': 2, 'handle': '2'},
            {'user_id': 3, 'handle': '3'}
        ],
        'follows': [
            {"follower_user_id": 1, "followee_user_id": 2},
            {"follower_user_id": 1, "followee_user_id": 3},
            {"follower_user_id": 2, "followee_user_id": 3}
        ]
    }

    populate_mock_db(db, test_entities)

    with db.scoped_session() as session:
        session.execute("REFRESH MATERIALIZED VIEW tag_track_user")
        session.execute("REFRESH MATERIALIZED VIEW aggregate_plays")
        args = {
            'search_str': 'pop',
            'current_user_id': None,
            'user_tag_count': 2,
            'limit': 10,
            'offset': 0
        }
        users = search_user_tags(session, args)

        assert len(users) == 2
        assert users[0]['user_id'] == 2 # Fir. b/c user 2 has 1 follower
        assert users[1]['user_id'] == 1 # Sec. b/c user 1 has 0 followers
def test_search_track_tags(app):
    """Tests that search by tags works fopr tracks"""
    with app.app_context():
        db = get_db()

    test_entities = {
        'tracks': [
            {"track_id": 1, "tags": "", "owner_id": 1},
            {"track_id": 2, "owner_id": 1, "tags": "pop,rock,electric"},
            {"track_id": 3, "owner_id": 2},
            {"track_id": 4, "owner_id": 2, "tags": "funk,pop"},
            {"track_id": 5, "owner_id": 2, "tags": "funk,pop"},
            {"track_id": 6, "owner_id": 2, "tags": "funk,Funk,kpop"}
        ],
        'plays': [
            {'item_id': 1},
            {'item_id': 1},
            {'item_id': 2},
            {'item_id': 2},
            {'item_id': 4},
            {'item_id': 5},
            {'item_id': 5},
            {'item_id': 5}
        ]
    }

    populate_mock_db(db, test_entities)

    with db.scoped_session() as session:
        session.execute("REFRESH MATERIALIZED VIEW tag_track_user")
        session.execute("REFRESH MATERIALIZED VIEW aggregate_plays")
        args = {
            'search_str': 'pop',
            'current_user_id': None,
            'limit': 10,
            'offset': 0
        }
        tracks = search_track_tags(session, args)

        assert len(tracks) == 3
        assert tracks[0]['track_id'] == 5 # First w/ 3 plays
        assert tracks[1]['track_id'] == 2 # Sec w/ 2 plays
        assert tracks[2]['track_id'] == 4 # Third w/ 1 plays
def test_populate_user_metadata(app):
    """Tests that populate_user_metadata works after aggregate_user refresh"""
    with app.app_context():
        db = get_db()

    test_entities = {
        'tracks': [{
            "track_id": 1,
            "owner_id": 1
        }, {
            "track_id": 2,
            "owner_id": 1
        }, {
            "track_id": 3,
            "owner_id": 2
        }, {
            "track_id": 4,
            "owner_id": 2
        }, {
            "track_id": 5,
            "owner_id": 2
        }, {
            "track_id": 6,
            "owner_id": 2
        }, {
            "track_id": 7,
            "owner_id": 3
        }, {
            "track_id": 8,
            "owner_id": 3
        }, {
            "track_id": 8,
            "owner_id": 3
        }, {
            "track_id": 9,
            "is_unlisted": True,
            "owner_id": 3
        }],
        'playlists': [
            {
                "playlist_id": 1,
                "playlist_owner_id": 1
            },
            {
                "playlist_id": 2,
                "playlist_owner_id": 1
            },
            {
                "playlist_id": 3,
                "is_album": True,
                "playlist_owner_id": 1
            },
            {
                "playlist_id": 4,
                "playlist_owner_id": 2
            },
            {
                "playlist_id": 5,
                "is_delete": True,
                "playlist_owner_id": 2
            },
            {
                "playlist_id": 6,
                "is_album": True,
                "playlist_owner_id": 3
            },
            {
                "playlist_id": 6,
                "is_private": True,
                "playlist_owner_id": 3
            },
        ],
        'users': [{
            'user_id': 1,
            'handle': 'user1'
        }, {
            'user_id': 2,
            'handle': 'user2'
        }, {
            'user_id': 3,
            'handle': 'user3'
        }, {
            'user_id': 4,
            'handle': 'user4'
        }],
        'follows': [{
            "follower_user_id": 1,
            "followee_user_id": 2
        }, {
            "follower_user_id": 1,
            "followee_user_id": 3
        }, {
            "follower_user_id": 2,
            "followee_user_id": 3
        }],
        'reposts': [{
            "repost_item_id": 1,
            "repost_type": 'track',
            "user_id": 2
        }, {
            "repost_item_id": 1,
            "repost_type": 'playlist',
            "user_id": 2
        }, {
            "repost_item_id": 1,
            "repost_type": 'track',
            "user_id": 3
        }, {
            "repost_item_id": 1,
            "repost_type": 'playlist',
            "user_id": 3
        }, {
            "repost_item_id": 4,
            "repost_type": 'track',
            "user_id": 1
        }, {
            "repost_item_id": 5,
            "repost_type": 'track',
            "user_id": 1
        }, {
            "repost_item_id": 6,
            "repost_type": 'track',
            "user_id": 1
        }],
        'saves': [{
            "save_item_id": 1,
            "save_type": 'track',
            "user_id": 2
        }, {
            "save_item_id": 1,
            "save_type": 'playlist',
            "user_id": 2
        }, {
            "save_item_id": 1,
            "save_type": 'track',
            "user_id": 3
        }, {
            "save_item_id": 1,
            "save_type": 'playlist',
            "user_id": 3
        }, {
            "save_item_id": 4,
            "save_type": 'track',
            "user_id": 1
        }, {
            "save_item_id": 5,
            "save_type": 'track',
            "user_id": 1
        }, {
            "save_item_id": 6,
            "save_type": 'track',
            "user_id": 1
        }]
    }

    populate_mock_db(db, test_entities)

    with db.scoped_session() as session:
        session.execute("REFRESH MATERIALIZED VIEW aggregate_user")
        user_ids = [1, 2, 3, 4, 5]
        users = [{
            "user_id": 1,
            "is_verified": False
        }, {
            "user_id": 2,
            "is_verified": False
        }, {
            "user_id": 3,
            "is_verified": False
        }, {
            "user_id": 4,
            "is_verified": False
        }, {
            "user_id": 5,
            "is_verified": False
        }]

        users = populate_user_metadata(session, user_ids, users, None)
        assert len(users) == 5

        assert users[0]['user_id'] == 1
        assert users[0][response_name_constants.track_count] == 2
        assert users[0][response_name_constants.playlist_count] == 2
        assert users[0][response_name_constants.album_count] == 1
        assert users[0][response_name_constants.follower_count] == 0
        assert users[0][response_name_constants.followee_count] == 2
        assert users[0][response_name_constants.repost_count] == 3

        assert users[1]['user_id'] == 2
        assert users[1][response_name_constants.track_count] == 4
        assert users[1][response_name_constants.playlist_count] == 1
        assert users[1][response_name_constants.album_count] == 0
        assert users[1][response_name_constants.follower_count] == 1
        assert users[1][response_name_constants.followee_count] == 1
        assert users[1][response_name_constants.repost_count] == 2

        assert users[2]['user_id'] == 3
        assert users[2][response_name_constants.track_count] == 3
        assert users[2][response_name_constants.playlist_count] == 0
        assert users[2][response_name_constants.album_count] == 1
        assert users[2][response_name_constants.follower_count] == 2
        assert users[2][response_name_constants.followee_count] == 0
        assert users[2][response_name_constants.repost_count] == 2

        assert users[3]['user_id'] == 4
        assert users[3][response_name_constants.track_count] == 0
        assert users[3][response_name_constants.playlist_count] == 0
        assert users[3][response_name_constants.album_count] == 0
        assert users[3][response_name_constants.follower_count] == 0
        assert users[3][response_name_constants.followee_count] == 0
        assert users[3][response_name_constants.repost_count] == 0

        assert users[4]['user_id'] == 5
        assert users[4][response_name_constants.track_count] == 0
        assert users[4][response_name_constants.playlist_count] == 0
        assert users[4][response_name_constants.album_count] == 0
        assert users[4][response_name_constants.follower_count] == 0
        assert users[4][response_name_constants.followee_count] == 0
        assert users[4][response_name_constants.repost_count] == 0

        curr_user_ids = [1, 2, 3]
        curr_users = [{
            "user_id": 1,
            "is_verified": False
        }, {
            "user_id": 2,
            "is_verified": False
        }, {
            "user_id": 3,
            "is_verified": False
        }]

        users = populate_user_metadata(session, curr_user_ids, curr_users, 1)
        assert len(users) == 3

        assert users[0]['user_id'] == 1
        assert users[0][
            response_name_constants.does_current_user_follow] == False
        assert users[0][
            response_name_constants.current_user_followee_follow_count] == 0
        assert users[0][response_name_constants.balance] == '0'
        assert users[0][
            response_name_constants.associated_wallets_balance] == '0'

        assert users[1]['user_id'] == 2
        assert users[1][
            response_name_constants.does_current_user_follow] == True
        assert users[1][
            response_name_constants.current_user_followee_follow_count] == 0
        assert users[1][response_name_constants.balance] == '0'
        assert users[1][
            response_name_constants.associated_wallets_balance] == '0'

        assert users[2]['user_id'] == 3
        assert users[2][
            response_name_constants.does_current_user_follow] == True
        assert users[2][
            response_name_constants.current_user_followee_follow_count] == 1
        assert users[2][response_name_constants.balance] == '0'
        assert users[2][
            response_name_constants.associated_wallets_balance] == '0'
Exemple #6
0
def test_populate_playlist_metadata(app):
    """Tests that populate_playlist_metadata works after aggregate_user refresh"""
    with app.app_context():
        db = get_db()

    test_entities = {
        'playlists': [{
            "playlist_id": 1,
            "playlist_owner_id": 1
        }, {
            "playlist_id": 2,
            "playlist_owner_id": 1
        }, {
            "playlist_id": 3,
            "playlist_owner_id": 2
        }, {
            "playlist_id": 4,
            "playlist_owner_id": 3
        }],
        'users': [{
            'user_id': 1,
            'handle': 'user1'
        }, {
            'user_id': 2,
            'handle': 'user2'
        }, {
            'user_id': 3,
            'handle': 'user3'
        }, {
            'user_id': 4,
            'handle': 'user4'
        }],
        'reposts': [{
            "repost_item_id": 1,
            "repost_type": 'playlist',
            "user_id": 2
        }, {
            "repost_item_id": 1,
            "repost_type": 'playlist',
            "user_id": 3
        }, {
            "repost_item_id": 2,
            "repost_type": 'playlist',
            "user_id": 1
        }],
        'saves': [{
            "save_item_id": 1,
            "save_type": 'playlist',
            "user_id": 2
        }, {
            "save_item_id": 1,
            "save_type": 'playlist',
            "user_id": 3
        }, {
            "save_item_id": 3,
            "save_type": 'playlist',
            "user_id": 2
        }, {
            "save_item_id": 3,
            "save_type": 'playlist',
            "user_id": 1
        }],
        'follows': [{
            "follower_user_id": 1,
            "followee_user_id": 2
        }, {
            "follower_user_id": 1,
            "followee_user_id": 3
        }]
    }

    populate_mock_db(db, test_entities)

    with db.scoped_session() as session:
        session.execute("REFRESH MATERIALIZED VIEW aggregate_playlist")
        playlist_ids = [1, 2, 3, 4]
        playlists = [{
            "playlist_id": 1,
            "playlist_contents": {
                "track_ids": []
            }
        }, {
            "playlist_id": 2,
            "playlist_contents": {
                "track_ids": []
            }
        }, {
            "playlist_id": 3,
            "playlist_contents": {
                "track_ids": []
            }
        }, {
            "playlist_id": 4,
            "playlist_contents": {
                "track_ids": []
            }
        }]

        playlists = populate_playlist_metadata(
            session, playlist_ids, playlists,
            [RepostType.playlist, RepostType.album],
            [SaveType.playlist, SaveType.album], None)
        assert len(playlists) == 4
        assert playlists[0]['playlist_id'] == 1
        assert playlists[0][response_name_constants.repost_count] == 2
        assert playlists[0][response_name_constants.save_count] == 2
        assert playlists[0][response_name_constants.total_play_count] == 0

        assert playlists[1]['playlist_id'] == 2
        assert playlists[1][response_name_constants.repost_count] == 1
        assert playlists[1][response_name_constants.save_count] == 0
        assert playlists[1][response_name_constants.total_play_count] == 0

        assert playlists[2]['playlist_id'] == 3
        assert playlists[2][response_name_constants.repost_count] == 0
        assert playlists[2][response_name_constants.save_count] == 2
        assert playlists[2][response_name_constants.total_play_count] == 0

        curr_playlist_ids = [1, 2, 3]
        curr_playlists = [{
            "playlist_id": 1,
            "playlist_contents": {
                "track_ids": []
            }
        }, {
            "playlist_id": 2,
            "playlist_contents": {
                "track_ids": []
            }
        }, {
            "playlist_id": 3,
            "playlist_contents": {
                "track_ids": []
            }
        }]

        playlists = populate_playlist_metadata(
            session, curr_playlist_ids, curr_playlists,
            [RepostType.playlist, RepostType.album],
            [SaveType.playlist, SaveType.album], 1)
        assert len(playlists) == 3

        assert playlists[0]['playlist_id'] == 1
        repost_user_ids = [
            repost['user_id'] for repost in playlists[0][
                response_name_constants.followee_reposts]
        ]
        repost_user_ids.sort()
        assert repost_user_ids == [2, 3]
        save_user_ids = [
            save['user_id']
            for save in playlists[0][response_name_constants.followee_saves]
        ]
        save_user_ids.sort()
        assert save_user_ids == [2, 3]
        assert playlists[0][
            response_name_constants.has_current_user_reposted] == False
        assert playlists[0][
            response_name_constants.has_current_user_saved] == False

        assert playlists[1]['playlist_id'] == 2
        assert playlists[1][response_name_constants.followee_reposts] == []
        assert playlists[1][response_name_constants.followee_saves] == []
        assert playlists[1][
            response_name_constants.has_current_user_reposted] == True
        assert playlists[1][
            response_name_constants.has_current_user_saved] == False

        assert playlists[2]['playlist_id'] == 3
        assert playlists[2][response_name_constants.followee_reposts] == []
        save_user_ids = [
            save['user_id']
            for save in playlists[2][response_name_constants.followee_saves]
        ]
        save_user_ids.sort()
        assert save_user_ids == [2]
        assert playlists[2][
            response_name_constants.has_current_user_reposted] == False
        assert playlists[2][
            response_name_constants.has_current_user_saved] == True
def test_populate_track_metadata(app):
    """Tests that populate_track_metadata works after aggregate_user refresh"""
    with app.app_context():
        db = get_db()

    test_entities = {
        'tracks': [{
            "track_id": 1,
            "owner_id": 1
        }, {
            "track_id": 2,
            "owner_id": 1
        }, {
            "track_id": 3,
            "owner_id": 2
        }, {
            "track_id": 4,
            "owner_id": 2
        }, {
            "track_id": 5,
            "owner_id": 2
        }, {
            "track_id": 6,
            "owner_id": 2
        }, {
            "track_id": 7,
            "owner_id": 3
        }, {
            "track_id": 8,
            "owner_id": 3
        }, {
            "track_id": 9,
            "owner_id": 3
        }, {
            "track_id": 10,
            "is_unlisted": True,
            "owner_id": 3
        }],
        'users': [{
            'user_id': 1,
            'handle': 'user1'
        }, {
            'user_id': 2,
            'handle': 'user2'
        }, {
            'user_id': 3,
            'handle': 'user3'
        }, {
            'user_id': 4,
            'handle': 'user4'
        }],
        'reposts': [{
            "repost_item_id": 1,
            "repost_type": 'track',
            "user_id": 2
        }, {
            "repost_item_id": 1,
            "repost_type": 'track',
            "user_id": 3
        }, {
            "repost_item_id": 2,
            "repost_type": 'track',
            "user_id": 1
        }],
        'saves': [{
            "save_item_id": 1,
            "save_type": 'track',
            "user_id": 2
        }, {
            "save_item_id": 1,
            "save_type": 'track',
            "user_id": 3
        }, {
            "save_item_id": 3,
            "save_type": 'track',
            "user_id": 2
        }, {
            "save_item_id": 3,
            "save_type": 'track',
            "user_id": 1
        }],
        'follows': [{
            "follower_user_id": 1,
            "followee_user_id": 2
        }, {
            "follower_user_id": 1,
            "followee_user_id": 3
        }]
    }

    populate_mock_db(db, test_entities)

    with db.scoped_session() as session:
        session.execute("REFRESH MATERIALIZED VIEW aggregate_track")
        track_ids = [1, 2, 3]
        tracks = [
            {
                "track_id": 1
            },
            {
                "track_id": 2
            },
            {
                "track_id": 3
            },
        ]

        tracks = populate_track_metadata(session, track_ids, tracks, None)
        assert len(tracks) == 3

        assert tracks[0]['track_id'] == 1
        assert tracks[0][response_name_constants.repost_count] == 2
        assert tracks[0][response_name_constants.save_count] == 2
        assert tracks[0][response_name_constants.play_count] == 0

        assert tracks[1]['track_id'] == 2
        assert tracks[1][response_name_constants.repost_count] == 1
        assert tracks[1][response_name_constants.save_count] == 0
        assert tracks[1][response_name_constants.play_count] == 0

        assert tracks[2]['track_id'] == 3
        assert tracks[2][response_name_constants.repost_count] == 0
        assert tracks[2][response_name_constants.save_count] == 2
        assert tracks[2][response_name_constants.play_count] == 0

        curr_track_ids = [1, 2, 3]
        curr_tracks = [{"track_id": 1}, {"track_id": 2}, {"track_id": 3}]

        tracks = populate_track_metadata(session, curr_track_ids, curr_tracks,
                                         1)
        assert len(tracks) == 3

        assert tracks[0]['track_id'] == 1
        repost_user_ids = [
            repost['user_id']
            for repost in tracks[0][response_name_constants.followee_reposts]
        ]
        repost_user_ids.sort()
        assert repost_user_ids == [2, 3]
        save_user_ids = [
            save['user_id']
            for save in tracks[0][response_name_constants.followee_saves]
        ]
        save_user_ids.sort()
        assert save_user_ids == [2, 3]
        assert tracks[0][
            response_name_constants.has_current_user_reposted] == False
        assert tracks[0][
            response_name_constants.has_current_user_saved] == False

        assert tracks[1]['track_id'] == 2
        assert tracks[1][response_name_constants.followee_reposts] == []
        assert tracks[1][response_name_constants.followee_saves] == []
        assert tracks[1][
            response_name_constants.has_current_user_reposted] == True
        assert tracks[1][
            response_name_constants.has_current_user_saved] == False

        assert tracks[2]['track_id'] == 3
        assert tracks[2][response_name_constants.followee_reposts] == []
        save_user_ids = [
            save['user_id']
            for save in tracks[2][response_name_constants.followee_saves]
        ]
        save_user_ids.sort()
        assert save_user_ids == [2]
        assert tracks[2][
            response_name_constants.has_current_user_reposted] == False
        assert tracks[2][
            response_name_constants.has_current_user_saved] == True
def test_track_tag_mat_view(app):
    """Tests that genre metrics can be queried"""
    with app.app_context():
        db = get_db()

    test_entities = {
        'tracks': [{
            "track_id": 1,
            "tags": "",
            "owner_id": 1
        }, {
            "track_id": 2,
            "owner_id": 1,
            "tags": "pop,rock,electric"
        }, {
            "track_id": 3,
            "owner_id": 2
        }, {
            "track_id": 4,
            "owner_id": 2,
            "tags": "funk,pop"
        }, {
            "track_id": 5,
            "owner_id": 2,
            "tags": "funk,pop"
        }, {
            "track_id": 6,
            "owner_id": 2,
            "tags": "funk,Funk,kpop"
        }]
    }

    populate_mock_db(db, test_entities)

    with db.scoped_session() as session:
        session.execute("REFRESH MATERIALIZED VIEW tag_track_user")
        user_1_tags = (session.query(TagTrackUserMatview).filter(
            TagTrackUserMatview.owner_id == 1).order_by(
                asc(TagTrackUserMatview.tag),
                asc(TagTrackUserMatview.track_id)).all())
        user_2_tags = (session.query(TagTrackUserMatview).filter(
            TagTrackUserMatview.owner_id == 2).order_by(
                asc(TagTrackUserMatview.tag),
                asc(TagTrackUserMatview.track_id)).all())
        user_4_tags = session.query(TagTrackUserMatview).filter(
            TagTrackUserMatview.owner_id == 4).all()

        assert len(user_1_tags) == 3
        assert user_1_tags[0].tag == 'electric'
        assert user_1_tags[0].track_id == 2
        assert user_1_tags[1].tag == 'pop'
        assert user_1_tags[1].track_id == 2
        assert user_1_tags[2].tag == 'rock'
        assert user_1_tags[2].track_id == 2

        assert len(user_2_tags) == 6
        assert user_2_tags[0].tag == 'funk'
        assert user_2_tags[0].track_id == 4
        assert user_2_tags[1].tag == 'funk'
        assert user_2_tags[1].track_id == 5
        assert user_2_tags[2].tag == 'funk'
        assert user_2_tags[2].track_id == 6
        assert user_2_tags[3].tag == 'kpop'
        assert user_2_tags[3].track_id == 6
        assert user_2_tags[4].tag == 'pop'
        assert user_2_tags[4].track_id == 4
        assert user_2_tags[5].tag == 'pop'
        assert user_2_tags[5].track_id == 5

        assert not user_4_tags