Esempio n. 1
0
class testPagerankFlow(FlowTestsBase):
    def __init__(self):
        self.env = Env()
        global redis_graph
        redis_con = self.env.getConnection()
        redis_graph = Graph(GRAPH_ID, redis_con)

    def test_pagerank(self):
        # Pagerank considers only nodes of given label and
        # relation of given relationship type
        # multiple edges between two nodes are considered as a single connection.
        queries = [
            # Single Label, single connection.
            "CREATE (a:L {v:1})-[:R]->(b:L {v:2})",
            # Single Label, multi connection.
            "CREATE (a:L {v:1})-[:R]->(b:L {v:2}), (a)-[:R]->(b)",
            # Multi Label, single connection.
            "CREATE (a:L {v:1})-[:R]->(b:L {v:2}), (:X)-[:R]->(:X)",
            # Multi Label, multi connection.
            "CREATE (a:L {v:1})-[:R]->(b:L {v:2}), (a)-[:R]->(b), (:X)-[:R]->(:X)"
        ]

        for q in queries:
            self.env.cmd('flushall')
            redis_graph.query(q)
            q = """CALL algo.pageRank('L', 'R') YIELD node, score RETURN node.v, score"""
            resultset = redis_graph.query(q).result_set

            # 2) 1) 1) (integer) 2
            # 2) "0.777813196182251"
            # 2) 1) (integer) 1
            # 2) "0.22218681871891"
            self.env.assertEqual(len(resultset), 2)
            self.env.assertEqual(resultset[0][0], 2)
            self.env.assertAlmostEqual(resultset[0][1], 0.777813196182251,
                                       0.0001)
            self.env.assertEqual(resultset[1][0], 1)
            self.env.assertAlmostEqual(resultset[1][1], 0.22218681871891,
                                       0.0001)
Esempio n. 2
0
class TestAggregate():
    def __init__(self):
        self.env = Env()
        add_values(self.env)

    def testGroupBy(self):
        cmd = [
            'ft.aggregate', 'games', '*', 'GROUPBY', '1', '@brand', 'REDUCE',
            'count', '0', 'AS', 'count', 'SORTBY', 2, '@count', 'desc',
            'LIMIT', '0', '5'
        ]

        res = self.env.cmd(*cmd)
        self.env.assertIsNotNone(res)
        self.env.assertEqual([
            292L, ['brand', '', 'count', '1518'],
            ['brand', 'mad catz', 'count', '43'],
            ['brand', 'generic', 'count', '40'],
            ['brand', 'steelseries', 'count', '37'],
            ['brand', 'logitech', 'count', '35']
        ], res)

    def testMinMax(self):
        cmd = [
            'ft.aggregate', 'games', 'sony', 'GROUPBY', '1', '@brand',
            'REDUCE', 'count', '0', 'REDUCE', 'min', '1', '@price', 'as',
            'minPrice', 'SORTBY', '2', '@minPrice', 'DESC'
        ]
        res = self.env.cmd(*cmd)
        self.env.assertIsNotNone(res)
        row = to_dict(res[1])
        self.env.assertEqual(88, int(float(row['minPrice'])))

        cmd = [
            'ft.aggregate', 'games', 'sony', 'GROUPBY', '1', '@brand',
            'REDUCE', 'count', '0', 'REDUCE', 'max', '1', '@price', 'as',
            'maxPrice', 'SORTBY', '2', '@maxPrice', 'DESC'
        ]
        res = self.env.cmd(*cmd)
        row = to_dict(res[1])
        self.env.assertEqual(695, int(float(row['maxPrice'])))

    def testAvg(self):
        cmd = [
            'ft.aggregate', 'games', 'sony', 'GROUPBY', '1', '@brand',
            'REDUCE', 'avg', '1', '@price', 'AS', 'avg_price', 'REDUCE',
            'count', '0', 'SORTBY', '2', '@avg_price', 'DESC'
        ]
        res = self.env.cmd(*cmd)
        self.env.assertIsNotNone(res)
        self.env.assertEqual(26, res[0])
        # Ensure the formatting actually exists

        first_row = to_dict(res[1])
        self.env.assertEqual(109, int(float(first_row['avg_price'])))

        for row in res[1:]:
            row = to_dict(row)
            self.env.assertIn('avg_price', row)

        # Test aliasing
        cmd = [
            'FT.AGGREGATE', 'games', 'sony', 'GROUPBY', '1', '@brand',
            'REDUCE', 'avg', '1', '@price', 'AS', 'avgPrice'
        ]
        res = self.env.cmd(*cmd)
        first_row = to_dict(res[1])
        self.env.assertEqual(17, int(float(first_row['avgPrice'])))

    def testCountDistinct(self):
        cmd = [
            'FT.AGGREGATE', 'games', '*', 'GROUPBY', '1', '@brand', 'REDUCE',
            'COUNT_DISTINCT', '1', '@title', 'AS', 'count_distinct(title)',
            'REDUCE', 'COUNT', '0'
        ]
        res = self.env.cmd(*cmd)[1:]
        # print res
        row = to_dict(res[0])
        self.env.assertEqual(1484, int(row['count_distinct(title)']))

        cmd = [
            'FT.AGGREGATE', 'games', '*', 'GROUPBY', '1', '@brand', 'REDUCE',
            'COUNT_DISTINCTISH', '1', '@title', 'AS',
            'count_distinctish(title)', 'REDUCE', 'COUNT', '0'
        ]
        res = self.env.cmd(*cmd)[1:]
        # print res
        row = to_dict(res[0])
        self.env.assertEqual(1461, int(row['count_distinctish(title)']))

    def testQuantile(self):
        cmd = [
            'FT.AGGREGATE', 'games', '*', 'GROUPBY', '1', '@brand', 'REDUCE',
            'QUANTILE', '2', '@price', '0.50', 'AS', 'q50', 'REDUCE',
            'QUANTILE', '2', '@price', '0.90', 'AS', 'q90', 'REDUCE',
            'QUANTILE', '2', '@price', '0.95', 'AS', 'q95', 'REDUCE', 'AVG',
            '1', '@price', 'REDUCE', 'COUNT', '0', 'AS', 'rowcount', 'SORTBY',
            '2', '@rowcount', 'DESC', 'MAX', '1'
        ]

        res = self.env.cmd(*cmd)
        row = to_dict(res[1])
        # TODO: Better samples
        self.env.assertAlmostEqual(14.99, float(row['q50']), delta=3)
        self.env.assertAlmostEqual(70, float(row['q90']), delta=50)

        # This tests the 95th percentile, which is error prone because
        # so few samples actually exist. I'm disabling it for now so that
        # there is no breakage in CI
        # self.env.assertAlmostEqual(110, (float(row['q95'])), delta=50)

    def testStdDev(self):
        cmd = [
            'FT.AGGREGATE', 'games', '*', 'GROUPBY', '1', '@brand', 'REDUCE',
            'STDDEV', '1', '@price', 'AS', 'stddev(price)', 'REDUCE', 'AVG',
            '1', '@price', 'AS', 'avgPrice', 'REDUCE', 'QUANTILE', '2',
            '@price', '0.50', 'AS', 'q50Price', 'REDUCE', 'COUNT', '0', 'AS',
            'rowcount', 'SORTBY', '2', '@rowcount', 'DESC', 'LIMIT', '0', '10'
        ]
        res = self.env.cmd(*cmd)
        row = to_dict(res[1])

        self.env.assertTrue(10 <= int(float(row['q50Price'])) <= 20)
        self.env.assertAlmostEqual(53,
                                   int(float(row['stddev(price)'])),
                                   delta=50)
        self.env.assertEqual(29, int(float(row['avgPrice'])))

    def testParseTime(self):
        cmd = [
            'FT.AGGREGATE', 'games', '*', 'GROUPBY', '1', '@brand', 'REDUCE',
            'COUNT', '0', 'AS', 'count', 'APPLY', 'timefmt(1517417144)', 'AS',
            'dt', 'APPLY', 'parse_time("%FT%TZ", @dt)', 'as', 'parsed_dt',
            'LIMIT', '0', '1'
        ]
        res = self.env.cmd(*cmd)

        self.env.assertEqual([
            'brand', '', 'count', '1518', 'dt', '2018-01-31T16:45:44Z',
            'parsed_dt', '1517417144'
        ], res[1])

    def testRandomSample(self):
        cmd = [
            'FT.AGGREGATE', 'games', '*', 'GROUPBY', '1', '@brand', 'REDUCE',
            'COUNT', '0', 'AS', 'num', 'REDUCE', 'RANDOM_SAMPLE', '2',
            '@price', '10', 'SORTBY', '2', '@num', 'DESC', 'MAX', '10'
        ]
        for row in self.env.cmd(*cmd)[1:]:
            self.env.assertIsInstance(row[5], list)
            self.env.assertGreater(len(row[5]), 0)
            self.env.assertGreaterEqual(row[3], len(row[5]))

            self.env.assertLessEqual(len(row[5]), 10)

    def testTimeFunctions(self):
        cmd = [
            'FT.AGGREGATE', 'games', '*', 'APPLY', '1517417144', 'AS', 'dt',
            'APPLY', 'timefmt(@dt)', 'AS', 'timefmt', 'APPLY', 'day(@dt)',
            'AS', 'day', 'APPLY', 'hour(@dt)', 'AS', 'hour', 'APPLY',
            'minute(@dt)', 'AS', 'minute', 'APPLY', 'month(@dt)', 'AS',
            'month', 'APPLY', 'dayofweek(@dt)', 'AS', 'dayofweek', 'APPLY',
            'dayofmonth(@dt)', 'AS', 'dayofmonth', 'APPLY', 'dayofyear(@dt)',
            'AS', 'dayofyear', 'APPLY', 'year(@dt)', 'AS', 'year', 'LIMIT',
            '0', '1'
        ]
        res = self.env.cmd(*cmd)
        self.env.assertListEqual([
            1L,
            [
                'dt', '1517417144', 'timefmt', '2018-01-31T16:45:44Z', 'day',
                '1517356800', 'hour', '1517414400', 'minute', '1517417100',
                'month', '1514764800', 'dayofweek', '3', 'dayofmonth', '31',
                'dayofyear', '30', 'year', '2018'
            ]
        ], res)

    def testStringFormat(self):
        cmd = [
            'FT.AGGREGATE', 'games', '@brand:sony', 'GROUPBY', '2', '@title',
            '@brand', 'REDUCE', 'COUNT', '0', 'REDUCE', 'MAX', '1', '@price',
            'AS', 'price', 'APPLY',
            'format("%s|%s|%s|%s", @title, @brand, "Mark", @price)', 'as',
            'titleBrand', 'LIMIT', '0', '10'
        ]
        res = self.env.cmd(*cmd)
        for row in res[1:]:
            row = to_dict(row)
            expected = '%s|%s|%s|%g' % (row['title'], row['brand'], 'Mark',
                                        float(row['price']))
            self.env.assertEqual(expected, row['titleBrand'])

    def testSum(self):
        cmd = [
            'ft.aggregate', 'games', '*', 'GROUPBY', '1', '@brand', 'REDUCE',
            'count', '0', 'AS', 'count', 'REDUCE', 'sum', 1, '@price', 'AS',
            'sum(price)', 'SORTBY', 2, '@sum(price)', 'desc', 'LIMIT', '0', '5'
        ]
        res = self.env.cmd(*cmd)
        self.env.assertEqual([
            292L, ['brand', '', 'count', '1518', 'sum(price)', '44780.69'],
            ['brand', 'mad catz', 'count', '43', 'sum(price)', '3973.48'],
            ['brand', 'razer', 'count', '26', 'sum(price)', '2558.58'],
            ['brand', 'logitech', 'count', '35', 'sum(price)', '2329.21'],
            ['brand', 'steelseries', 'count', '37', 'sum(price)', '1851.12']
        ], res)

    def testFilter(self):
        cmd = [
            'ft.aggregate', 'games', '*', 'GROUPBY', '1', '@brand', 'REDUCE',
            'count', '0', 'AS', 'count', 'FILTER', '@count > 5'
        ]

        res = self.env.cmd(*cmd)
        for row in res[1:]:
            row = to_dict(row)
            self.env.assertGreater(int(row['count']), 5)

        cmd = [
            'ft.aggregate', 'games', '*', 'GROUPBY', '1', '@brand', 'REDUCE',
            'count', '0', 'AS', 'count', 'FILTER', '@count < 5', 'FILTER',
            '@count > 2 && @brand != ""'
        ]

        res = self.env.cmd(*cmd)
        for row in res[1:]:
            row = to_dict(row)
            self.env.assertLess(int(row['count']), 5)
            self.env.assertGreater(int(row['count']), 2)

    def testToList(self):
        cmd = [
            'ft.aggregate', 'games', '*', 'GROUPBY', '1', '@brand', 'REDUCE',
            'count_distinct', '1', '@price', 'as', 'count', 'REDUCE', 'tolist',
            1, '@price', 'as', 'prices', 'SORTBY', 2, '@count', 'desc',
            'LIMIT', '0', '5'
        ]
        res = self.env.cmd(*cmd)

        for row in res[1:]:
            row = to_dict(row)
            self.env.assertEqual(int(row['count']), len(row['prices']))

    def testSortBy(self):
        res = self.env.cmd('ft.aggregate', 'games', '*', 'GROUPBY', '1',
                           '@brand', 'REDUCE', 'sum', 1, '@price', 'as',
                           'price', 'SORTBY', 2, '@price', 'desc', 'LIMIT',
                           '0', '2')

        self.env.assertListEqual([
            292L, ['brand', '', 'price', '44780.69'],
            ['brand', 'mad catz', 'price', '3973.48']
        ], res)

        res = self.env.cmd('ft.aggregate', 'games', '*', 'GROUPBY', '1',
                           '@brand', 'REDUCE', 'sum', 1, '@price', 'as',
                           'price', 'SORTBY', 2, '@price', 'asc', 'LIMIT', '0',
                           '2')

        self.env.assertListEqual([
            292L, ['brand', 'myiico', 'price', '0.23'],
            ['brand', 'crystal dynamics', 'price', '0.25']
        ], res)

        # Test MAX with limit higher than it
        res = self.env.cmd('ft.aggregate', 'games', '*', 'GROUPBY', '1',
                           '@brand', 'REDUCE', 'sum', 1, '@price', 'as',
                           'price', 'SORTBY', 2, '@price', 'asc', 'MAX', 2)

        self.env.assertListEqual([
            292L, ['brand', 'myiico', 'price', '0.23'],
            ['brand', 'crystal dynamics', 'price', '0.25']
        ], res)

        # Test Sorting by multiple properties
        res = self.env.cmd(
            'ft.aggregate',
            'games',
            '*',
            'GROUPBY',
            '1',
            '@brand',
            'REDUCE',
            'sum',
            1,
            '@price',
            'as',
            'price',
            'APPLY',
            '(@price % 10)',
            'AS',
            'price',
            'SORTBY',
            4,
            '@price',
            'asc',
            '@brand',
            'desc',
            'MAX',
            10,
        )
        self.env.assertListEqual([
            292L, ['brand', 'zps', 'price', '0'],
            ['brand', 'zalman', 'price', '0'], [
                'brand', 'yoozoo', 'price', '0'
            ], ['brand', 'white label', 'price', '0'],
            ['brand', 'stinky', 'price', '0'],
            ['brand', 'polaroid', 'price', '0'],
            ['brand', 'plantronics', 'price', '0'],
            ['brand', 'ozone', 'price', '0'], ['brand', 'oooo', 'price', '0'],
            ['brand', 'neon', 'price', '0']
        ], res)

    def testExpressions(self):
        pass

    def testNoGroup(self):
        res = self.env.cmd(
            'ft.aggregate',
            'games',
            '*',
            'LOAD',
            '2',
            '@brand',
            '@price',
            'APPLY',
            'floor(sqrt(@price)) % 10',
            'AS',
            'price',
            'SORTBY',
            4,
            '@price',
            'desc',
            '@brand',
            'desc',
            'MAX',
            5,
        )
        exp = [
            2265L, ['brand', 'xbox', 'price', '9'],
            ['brand', 'turtle beach', 'price', '9'],
            ['brand', 'trust', 'price', '9'],
            ['brand', 'steelseries', 'price', '9'],
            ['brand', 'speedlink', 'price', '9']
        ]
        # exp = [2265L, ['brand', 'Xbox', 'price', '9'], ['brand', 'Turtle Beach', 'price', '9'], [
        #  'brand', 'Trust', 'price', '9'], ['brand', 'SteelSeries', 'price', '9'], ['brand', 'Speedlink', 'price', '9']]
        self.env.assertListEqual(exp[1], res[1])

    def testLoad(self):
        res = self.env.cmd('ft.aggregate', 'games', '*', 'LOAD', '3', '@brand',
                           '@price', '@nonexist', 'SORTBY', 2, '@price',
                           'DESC', 'MAX', 2)
        exp = [
            3L, ['brand', '', 'price', '759.12'],
            ['brand', 'Sony', 'price', '695.8']
        ]
        self.env.assertEqual(exp[1], res[1])

    def testSplit(self):
        res = self.env.cmd(
            'ft.aggregate', 'games', '*', 'APPLY',
            'split("hello world,  foo,,,bar,", ",", " ")', 'AS', 'strs',
            'APPLY', 'split("hello world,  foo,,,bar,", " ", ",")', 'AS',
            'strs2', 'APPLY', 'split("hello world,  foo,,,bar,", "", "")',
            'AS', 'strs3', 'APPLY', 'split("hello world,  foo,,,bar,")', 'AS',
            'strs4', 'APPLY', 'split("hello world,  foo,,,bar,",",")', 'AS',
            'strs5', 'APPLY', 'split("")', 'AS', 'empty', 'LIMIT', '0', '1')
        # print "Got {} results".format(len(res))
        # return
        # pprint.pprint(res)
        self.env.assertListEqual([
            1L,
            [
                'strs', ['hello world', 'foo', 'bar'], 'strs2',
                ['hello', 'world', 'foo,,,bar'], 'strs3',
                ['hello world,  foo,,,bar,'], 'strs4',
                ['hello world', 'foo', 'bar'], 'strs5',
                ['hello world', 'foo', 'bar'], 'empty', []
            ]
        ], res)

    def testFirstValue(self):
        res = self.env.cmd(
            'ft.aggregate', 'games',
            '@brand:(sony|matias|beyerdynamic|(mad catz))', 'GROUPBY', 1,
            '@brand', 'REDUCE', 'FIRST_VALUE', 4, '@title', 'BY', '@price',
            'DESC', 'AS', 'top_item', 'REDUCE', 'FIRST_VALUE', 4, '@price',
            'BY', '@price', 'DESC', 'AS', 'top_price', 'REDUCE', 'FIRST_VALUE',
            4, '@title', 'BY', '@price', 'ASC', 'AS', 'bottom_item', 'REDUCE',
            'FIRST_VALUE', 4, '@price', 'BY', '@price', 'ASC', 'AS',
            'bottom_price', 'SORTBY', 2, '@top_price', 'DESC', 'MAX', 5)
        expected = [
            4L,
            [
                'brand', 'sony', 'top_item',
                'sony psp slim &amp; lite 2000 console', 'top_price', '695.8',
                'bottom_item',
                'sony dlchd20p high speed hdmi cable for playstation 3',
                'bottom_price', '5.88'
            ],
            [
                'brand', 'matias', 'top_item', 'matias halfkeyboard usb',
                'top_price', '559.99', 'bottom_item',
                'matias halfkeyboard usb', 'bottom_price', '559.99'
            ],
            [
                'brand', 'beyerdynamic', 'top_item',
                'beyerdynamic mmx300 pc gaming premium digital headset with microphone',
                'top_price', '359.74', 'bottom_item',
                'beyerdynamic headzone pc gaming digital surround sound system with mmx300 digital headset with microphone',
                'bottom_price', '0'
            ],
            [
                'brand', 'mad catz', 'top_item',
                'mad catz s.t.r.i.k.e.7 gaming keyboard', 'top_price',
                '295.95', 'bottom_item',
                'madcatz mov4545 xbox replacement breakaway cable',
                'bottom_price', '3.49'
            ]
        ]
        self.env.assertListEqual(expected, res)

    def testLoadAfterGroupBy(self):
        with self.env.assertResponseError():
            self.env.cmd('ft.aggregate', 'games', '*', 'GROUPBY', 1, '@brand',
                         'LOAD', 1, '@brand')
class TestAggregate():
    def __init__(self):
        self.env = Env()
        add_values(self.env)

    def testGroupBy(self):
        cmd = [
            'ft.aggregate', 'games', '*', 'GROUPBY', '1', '@brand', 'REDUCE',
            'count', '0', 'AS', 'count', 'SORTBY', 2, '@count', 'desc',
            'LIMIT', '0', '5'
        ]

        res = self.env.cmd(*cmd)
        self.env.assertIsNotNone(res)
        self.env.assertEqual([
            292L, ['brand', '', 'count', '1518'],
            ['brand', 'mad catz', 'count', '43'],
            ['brand', 'generic', 'count', '40'],
            ['brand', 'steelseries', 'count', '37'],
            ['brand', 'logitech', 'count', '35']
        ], res)

    def testMinMax(self):
        cmd = [
            'ft.aggregate', 'games', 'sony', 'GROUPBY', '1', '@brand',
            'REDUCE', 'count', '0', 'REDUCE', 'min', '1', '@price', 'as',
            'minPrice', 'SORTBY', '2', '@minPrice', 'DESC'
        ]
        res = self.env.cmd(*cmd)
        self.env.assertIsNotNone(res)
        row = to_dict(res[1])
        self.env.assertEqual(88, int(float(row['minPrice'])))

        cmd = [
            'ft.aggregate', 'games', 'sony', 'GROUPBY', '1', '@brand',
            'REDUCE', 'count', '0', 'REDUCE', 'max', '1', '@price', 'as',
            'maxPrice', 'SORTBY', '2', '@maxPrice', 'DESC'
        ]
        res = self.env.cmd(*cmd)
        row = to_dict(res[1])
        self.env.assertEqual(695, int(float(row['maxPrice'])))

    def testAvg(self):
        cmd = [
            'ft.aggregate', 'games', 'sony', 'GROUPBY', '1', '@brand',
            'REDUCE', 'avg', '1', '@price', 'AS', 'avg_price', 'REDUCE',
            'count', '0', 'SORTBY', '2', '@avg_price', 'DESC'
        ]
        res = self.env.cmd(*cmd)
        self.env.assertIsNotNone(res)
        self.env.assertEqual(26, res[0])
        # Ensure the formatting actually exists

        first_row = to_dict(res[1])
        self.env.assertEqual(109, int(float(first_row['avg_price'])))

        for row in res[1:]:
            row = to_dict(row)
            self.env.assertIn('avg_price', row)

        # Test aliasing
        cmd = [
            'FT.AGGREGATE', 'games', 'sony', 'GROUPBY', '1', '@brand',
            'REDUCE', 'avg', '1', '@price', 'AS', 'avgPrice'
        ]
        res = self.env.cmd(*cmd)
        first_row = to_dict(res[1])
        self.env.assertEqual(17, int(float(first_row['avgPrice'])))

    def testCountDistinct(self):
        cmd = [
            'FT.AGGREGATE', 'games', '*', 'GROUPBY', '1', '@brand', 'REDUCE',
            'COUNT_DISTINCT', '1', '@title', 'AS', 'count_distinct(title)',
            'REDUCE', 'COUNT', '0'
        ]
        res = self.env.cmd(*cmd)[1:]
        # print res
        row = to_dict(res[0])
        self.env.assertEqual(1484, int(row['count_distinct(title)']))

        cmd = [
            'FT.AGGREGATE', 'games', '*', 'GROUPBY', '1', '@brand', 'REDUCE',
            'COUNT_DISTINCTISH', '1', '@title', 'AS',
            'count_distinctish(title)', 'REDUCE', 'COUNT', '0'
        ]
        res = self.env.cmd(*cmd)[1:]
        # print res
        row = to_dict(res[0])
        self.env.assertEqual(1461, int(row['count_distinctish(title)']))

    def testQuantile(self):
        cmd = [
            'FT.AGGREGATE', 'games', '*', 'GROUPBY', '1', '@brand', 'REDUCE',
            'QUANTILE', '2', '@price', '0.50', 'AS', 'q50', 'REDUCE',
            'QUANTILE', '2', '@price', '0.90', 'AS', 'q90', 'REDUCE',
            'QUANTILE', '2', '@price', '0.95', 'AS', 'q95', 'REDUCE', 'AVG',
            '1', '@price', 'REDUCE', 'COUNT', '0', 'AS', 'rowcount', 'SORTBY',
            '2', '@rowcount', 'DESC', 'MAX', '1'
        ]

        res = self.env.cmd(*cmd)
        row = to_dict(res[1])
        # TODO: Better samples
        self.env.assertAlmostEqual(14.99, float(row['q50']), delta=3)
        self.env.assertAlmostEqual(70, float(row['q90']), delta=50)
        self.env.assertAlmostEqual(110, (float(row['q95'])), delta=50)

    def testStdDev(self):
        cmd = [
            'FT.AGGREGATE', 'games', '*', 'GROUPBY', '1', '@brand', 'REDUCE',
            'STDDEV', '1', '@price', 'AS', 'stddev(price)', 'REDUCE', 'AVG',
            '1', '@price', 'AS', 'avgPrice', 'REDUCE', 'QUANTILE', '2',
            '@price', '0.50', 'AS', 'q50Price', 'REDUCE', 'COUNT', '0', 'AS',
            'rowcount', 'SORTBY', '2', '@rowcount', 'DESC', 'LIMIT', '0', '10'
        ]
        res = self.env.cmd(*cmd)
        row = to_dict(res[1])

        self.env.assertTrue(10 <= int(float(row['q50Price'])) <= 20)
        self.env.assertAlmostEqual(53,
                                   int(float(row['stddev(price)'])),
                                   delta=50)
        self.env.assertEqual(29, int(float(row['avgPrice'])))

    def testParseTime(self):
        cmd = [
            'FT.AGGREGATE', 'games', '*', 'GROUPBY', '1', '@brand', 'REDUCE',
            'COUNT', '0', 'AS', 'count', 'APPLY', 'timefmt(1517417144)', 'AS',
            'dt', 'APPLY', 'parse_time("%FT%TZ", @dt)', 'as', 'parsed_dt',
            'LIMIT', '0', '1'
        ]
        res = self.env.cmd(*cmd)

        self.env.assertEqual([
            'brand', '', 'count', '1518', 'dt', '2018-01-31T16:45:44Z',
            'parsed_dt', '1517417144'
        ], res[1])

    def testRandomSample(self):
        cmd = [
            'FT.AGGREGATE', 'games', '*', 'GROUPBY', '1', '@brand', 'REDUCE',
            'COUNT', '0', 'AS', 'num', 'REDUCE', 'RANDOM_SAMPLE', '2',
            '@price', '10', 'SORTBY', '2', '@num', 'DESC', 'MAX', '10'
        ]
        for row in self.env.cmd(*cmd)[1:]:
            self.env.assertIsInstance(row[5], list)
            self.env.assertGreater(len(row[5]), 0)
            self.env.assertGreaterEqual(row[3], len(row[5]))

            self.env.assertLessEqual(len(row[5]), 10)

    def testTimeFunctions(self):
        cmd = [
            'FT.AGGREGATE', 'games', '*', 'APPLY', '1517417144', 'AS', 'dt',
            'APPLY', 'timefmt(@dt)', 'AS', 'timefmt', 'APPLY', 'day(@dt)',
            'AS', 'day', 'APPLY', 'hour(@dt)', 'AS', 'hour', 'APPLY',
            'minute(@dt)', 'AS', 'minute', 'APPLY', 'month(@dt)', 'AS',
            'month', 'APPLY', 'dayofweek(@dt)', 'AS', 'dayofweek', 'APPLY',
            'dayofmonth(@dt)', 'AS', 'dayofmonth', 'APPLY', 'dayofyear(@dt)',
            'AS', 'dayofyear', 'APPLY', 'year(@dt)', 'AS', 'year', 'LIMIT',
            '0', '1'
        ]
        res = self.env.cmd(*cmd)
        self.env.assertListEqual([
            1L,
            [
                'dt', '1517417144', 'timefmt', '2018-01-31T16:45:44Z', 'day',
                '1517356800', 'hour', '1517414400', 'minute', '1517417100',
                'month', '1514764800', 'dayofweek', '3', 'dayofmonth', '31',
                'dayofyear', '30', 'year', '2018'
            ]
        ], res)

    def testStringFormat(self):
        cmd = [
            'FT.AGGREGATE', 'games', '@brand:sony', 'GROUPBY', '2', '@title',
            '@brand', 'REDUCE', 'COUNT', '0', 'REDUCE', 'MAX', '1', '@price',
            'AS', 'price', 'APPLY',
            'format("%s|%s|%s|%s", @title, @brand, "Mark", @price)', 'as',
            'titleBrand', 'LIMIT', '0', '10'
        ]
        res = self.env.cmd(*cmd)
        for row in res[1:]:
            row = to_dict(row)
            expected = '%s|%s|%s|%g' % (row['title'], row['brand'], 'Mark',
                                        float(row['price']))
            self.env.assertEqual(expected, row['titleBrand'])

    def testSum(self):
        cmd = [
            'ft.aggregate', 'games', '*', 'GROUPBY', '1', '@brand', 'REDUCE',
            'count', '0', 'AS', 'count', 'REDUCE', 'sum', 1, '@price', 'AS',
            'sum(price)', 'SORTBY', 2, '@sum(price)', 'desc', 'LIMIT', '0', '5'
        ]
        res = self.env.cmd(*cmd)
        self.env.assertEqual([
            292L, ['brand', '', 'count', '1518', 'sum(price)', '44780.69'],
            ['brand', 'mad catz', 'count', '43', 'sum(price)', '3973.48'],
            ['brand', 'razer', 'count', '26', 'sum(price)', '2558.58'],
            ['brand', 'logitech', 'count', '35', 'sum(price)', '2329.21'],
            ['brand', 'steelseries', 'count', '37', 'sum(price)', '1851.12']
        ], res)

    def testFilter(self):
        cmd = [
            'ft.aggregate', 'games', '*', 'GROUPBY', '1', '@brand', 'REDUCE',
            'count', '0', 'AS', 'count', 'FILTER', '@count > 5'
        ]

        res = self.env.cmd(*cmd)
        for row in res[1:]:
            row = to_dict(row)
            self.env.assertGreater(int(row['count']), 5)

        cmd = [
            'ft.aggregate', 'games', '*', 'GROUPBY', '1', '@brand', 'REDUCE',
            'count', '0', 'AS', 'count', 'FILTER', '@count < 5', 'FILTER',
            '@count > 2 && @brand != ""'
        ]

        res = self.env.cmd(*cmd)
        for row in res[1:]:
            row = to_dict(row)
            self.env.assertLess(int(row['count']), 5)
            self.env.assertGreater(int(row['count']), 2)

    def testToList(self):
        cmd = [
            'ft.aggregate', 'games', '*', 'GROUPBY', '1', '@brand', 'REDUCE',
            'count_distinct', '1', '@price', 'as', 'count', 'REDUCE', 'tolist',
            1, '@price', 'as', 'prices', 'SORTBY', 2, '@count', 'desc',
            'LIMIT', '0', '5'
        ]
        res = self.env.cmd(*cmd)

        for row in res[1:]:
            row = to_dict(row)
            self.env.assertEqual(int(row['count']), len(row['prices']))

    def testSortBy(self):
        res = self.env.cmd('ft.aggregate', 'games', '*', 'GROUPBY', '1',
                           '@brand', 'REDUCE', 'sum', 1, '@price', 'as',
                           'price', 'SORTBY', 2, '@price', 'desc', 'LIMIT',
                           '0', '2')

        self.env.assertListEqual([
            292L, ['brand', '', 'price', '44780.69'],
            ['brand', 'mad catz', 'price', '3973.48']
        ], res)

        res = self.env.cmd('ft.aggregate', 'games', '*', 'GROUPBY', '1',
                           '@brand', 'REDUCE', 'sum', 1, '@price', 'as',
                           'price', 'SORTBY', 2, '@price', 'asc', 'LIMIT', '0',
                           '2')

        self.env.assertListEqual([
            292L, ['brand', 'myiico', 'price', '0.23'],
            ['brand', 'crystal dynamics', 'price', '0.25']
        ], res)

        # Test MAX with limit higher than it
        res = self.env.cmd('ft.aggregate', 'games', '*', 'GROUPBY', '1',
                           '@brand', 'REDUCE', 'sum', 1, '@price', 'as',
                           'price', 'SORTBY', 2, '@price', 'asc', 'MAX', 2)

        self.env.assertListEqual([
            292L, ['brand', 'myiico', 'price', '0.23'],
            ['brand', 'crystal dynamics', 'price', '0.25']
        ], res)

        # Test Sorting by multiple properties
        res = self.env.cmd(
            'ft.aggregate',
            'games',
            '*',
            'GROUPBY',
            '1',
            '@brand',
            'REDUCE',
            'sum',
            1,
            '@price',
            'as',
            'price',
            'APPLY',
            '(@price % 10)',
            'AS',
            'price',
            'SORTBY',
            4,
            '@price',
            'asc',
            '@brand',
            'desc',
            'MAX',
            10,
        )
        self.env.assertListEqual([
            292L, ['brand', 'zps', 'price', '0'],
            ['brand', 'zalman', 'price', '0'], [
                'brand', 'yoozoo', 'price', '0'
            ], ['brand', 'white label', 'price', '0'],
            ['brand', 'stinky', 'price', '0'],
            ['brand', 'polaroid', 'price', '0'],
            ['brand', 'plantronics', 'price', '0'],
            ['brand', 'ozone', 'price', '0'], ['brand', 'oooo', 'price', '0'],
            ['brand', 'neon', 'price', '0']
        ], res)

    def testExpressions(self):
        pass

    def testNoGroup(self):
        res = self.env.cmd(
            'ft.aggregate',
            'games',
            '*',
            'LOAD',
            '2',
            '@brand',
            '@price',
            'APPLY',
            'floor(sqrt(@price)) % 10',
            'AS',
            'price',
            'SORTBY',
            4,
            '@price',
            'desc',
            '@brand',
            'desc',
            'MAX',
            5,
        )
        exp = [
            2265L, ['brand', 'Xbox', 'price', '9'],
            ['brand', 'turtle beach', 'price', '9'],
            ['brand', 'trust', 'price', '9'],
            ['brand', 'steelseries', 'price', '9'],
            ['brand', 'speedlink', 'price', '9']
        ]
        # exp = [2265L, ['brand', 'Xbox', 'price', '9'], ['brand', 'Turtle Beach', 'price', '9'], [
        #  'brand', 'Trust', 'price', '9'], ['brand', 'SteelSeries', 'price', '9'], ['brand', 'Speedlink', 'price', '9']]
        self.env.assertListEqual(exp[1], res[1])

    def testLoad(self):
        res = self.env.cmd('ft.aggregate', 'games', '*', 'LOAD', '3', '@brand',
                           '@price', '@nonexist', 'SORTBY', 2, '@price',
                           'DESC', 'MAX', 2)
        exp = [
            3L, ['brand', '', 'price', '759.12'],
            ['brand', 'Sony', 'price', '695.8']
        ]
        self.env.assertEqual(exp[1], res[1])
        self.env.assertEqual(exp[2], res[2])

    def testLoadWithDocId(self):
        res = self.env.cmd('ft.aggregate', 'games', '*', 'LOAD', '3', '@brand',
                           '@price', '@__key', 'SORTBY', 2, '@price', 'DESC',
                           'MAX', 4)
        exp = [
            3L, ['brand', '', 'price', '759.12', '__key', 'B00006JJIC'],
            ['brand', 'Sony', 'price', '695.8', '__key', 'B000F6W1AG']
        ]
        self.env.assertEqual(exp[1], res[1])
        self.env.assertEqual(exp[2], res[2])

        res = self.env.cmd('ft.aggregate', 'games', '*', 'LOAD', '3', '@brand',
                           '@price', '@__key', 'FILTER',
                           '@__key == "B000F6W1AG"')
        self.env.assertEqual(
            res[1], ['brand', 'Sony', 'price', '695.8', '__key', 'B000F6W1AG'])

    def testLoadImplicit(self):
        # same as previous
        res = self.env.cmd('ft.aggregate', 'games', '*', 'LOAD', '1', '@brand',
                           'SORTBY', 2, '@price', 'DESC')
        exp = [
            3L, ['brand', '', 'price', '759.12'],
            ['brand', 'Sony', 'price', '695.8']
        ]
        self.env.assertEqual(exp[1], res[1])

    def testSplit(self):
        res = self.env.cmd(
            'ft.aggregate', 'games', '*', 'APPLY',
            'split("hello world,  foo,,,bar,", ",", " ")', 'AS', 'strs',
            'APPLY', 'split("hello world,  foo,,,bar,", " ", ",")', 'AS',
            'strs2', 'APPLY', 'split("hello world,  foo,,,bar,", "", "")',
            'AS', 'strs3', 'APPLY', 'split("hello world,  foo,,,bar,")', 'AS',
            'strs4', 'APPLY', 'split("hello world,  foo,,,bar,",",")', 'AS',
            'strs5', 'APPLY', 'split("")', 'AS', 'empty', 'LIMIT', '0', '1')
        # print "Got {} results".format(len(res))
        # return
        # pprint.pprint(res)
        self.env.assertListEqual([
            1L,
            [
                'strs', ['hello world', 'foo', 'bar'], 'strs2',
                ['hello', 'world', 'foo,,,bar'], 'strs3',
                ['hello world,  foo,,,bar,'], 'strs4',
                ['hello world', 'foo', 'bar'], 'strs5',
                ['hello world', 'foo', 'bar'], 'empty', []
            ]
        ], res)

    def testFirstValue(self):
        res = self.env.cmd(
            'ft.aggregate', 'games',
            '@brand:(sony|matias|beyerdynamic|(mad catz))', 'GROUPBY', 1,
            '@brand', 'REDUCE', 'FIRST_VALUE', 4, '@title', 'BY', '@price',
            'DESC', 'AS', 'top_item', 'REDUCE', 'FIRST_VALUE', 4, '@price',
            'BY', '@price', 'DESC', 'AS', 'top_price', 'REDUCE', 'FIRST_VALUE',
            4, '@title', 'BY', '@price', 'ASC', 'AS', 'bottom_item', 'REDUCE',
            'FIRST_VALUE', 4, '@price', 'BY', '@price', 'ASC', 'AS',
            'bottom_price', 'SORTBY', 2, '@top_price', 'DESC', 'MAX', 5)
        expected = [
            4L,
            [
                'brand', 'sony', 'top_item',
                'sony psp slim &amp; lite 2000 console', 'top_price', '695.8',
                'bottom_item',
                'sony dlchd20p high speed hdmi cable for playstation 3',
                'bottom_price', '5.88'
            ],
            [
                'brand', 'matias', 'top_item', 'matias halfkeyboard usb',
                'top_price', '559.99', 'bottom_item',
                'matias halfkeyboard usb', 'bottom_price', '559.99'
            ],
            [
                'brand', 'beyerdynamic', 'top_item',
                'beyerdynamic mmx300 pc gaming premium digital headset with microphone',
                'top_price', '359.74', 'bottom_item',
                'beyerdynamic headzone pc gaming digital surround sound system with mmx300 digital headset with microphone',
                'bottom_price', '0'
            ],
            [
                'brand', 'mad catz', 'top_item',
                'mad catz s.t.r.i.k.e.7 gaming keyboard', 'top_price',
                '295.95', 'bottom_item',
                'madcatz mov4545 xbox replacement breakaway cable',
                'bottom_price', '3.49'
            ]
        ]

        # hack :(
        def mklower(result):
            for arr in result[1:]:
                for x in range(len(arr)):
                    arr[x] = arr[x].lower()

        mklower(expected)
        mklower(res)
        self.env.assertListEqual(expected, res)

    def testLoadAfterGroupBy(self):
        with self.env.assertResponseError():
            self.env.cmd('ft.aggregate', 'games', '*', 'GROUPBY', 1, '@brand',
                         'LOAD', 1, '@brand')

    def testReducerGeneratedAliasing(self):
        rv = self.env.cmd('ft.aggregate', 'games', '*', 'GROUPBY', 1, '@brand',
                          'REDUCE', 'MIN', 1, '@price', 'LIMIT', 0, 1)
        self.env.assertEqual(
            [292L, ['brand', '', '__generated_aliasminprice', '0']], rv)

        rv = self.env.cmd('ft.aggregate', 'games',
                          '@brand:(sony|matias|beyerdynamic|(mad catz))',
                          'GROUPBY', 1, '@brand', 'REDUCE', 'FIRST_VALUE', 4,
                          '@title', 'BY', '@price', 'DESC', 'SORTBY', 2,
                          '@brand', 'ASC')
        self.env.assertEqual('__generated_aliasfirst_valuetitle,by,price,desc',
                             rv[1][2])

    def testIssue1125(self):
        self.env.skipOnCluster()
        # SEARCH should fail
        self.env.expect('ft.search', 'games', '*', 'limit', 0, 2000000).error()     \
                .contains('LIMIT exceeds maximum of 1000000')
        # SEARCH should succeed
        self.env.expect('ft.config', 'set', 'MAXSEARCHRESULTS', -1).ok()
        rv = self.env.cmd('ft.search', 'games', '*', 'LIMIT', 0, 12345678)
        self.env.assertEqual(4531, len(rv))
        # AGGREGATE should succeed
        rv = self.env.cmd('ft.aggregate', 'games', '*', 'LIMIT', 0, 12345678)
        self.env.assertEqual(2266, len(rv))
        # AGGREGATE should fail
        self.env.expect('ft.config', 'set', 'MAXAGGREGATERESULTS',
                        1000000).ok()
        self.env.expect('ft.aggregate', 'games', '*', 'limit', 0, 2000000).error()     \
                .contains('LIMIT exceeds maximum of 1000000')

        # force global limit on aggregate
        num = 10
        self.env.expect('ft.config', 'set', 'MAXAGGREGATERESULTS', num).ok()
        rv = self.env.cmd('ft.aggregate', 'games', '*')
        self.env.assertEqual(num + 1, len(rv))

    def testMultiSortBy(self):
        self.env.expect('ft.aggregate', 'games', '*',
                           'LOAD', '2', '@brand', '@price',
                           'SORTBY', 2, '@brand', 'DESC',
                           'SORTBY', 2, '@price', 'DESC').error()\
                            .contains('Multiple SORTBY steps are not allowed. Sort multiple fields in a single step')
Esempio n. 4
0
class testPath():
    def __init__(self):
        self.env = Env(decodeResponses=True)
        global redis_graph
        redis_con = self.env.getConnection()
        redis_graph = Graph(GRAPH_ID, redis_con)

    def setUp(self):
        self.env.flush()

    def assert_distance(self, a, b, expected_distance):
        # A is 18.07 km away from B
        q = """WITH point({latitude:%f, longitude:%f}) AS a,
        point({latitude:%f, longitude:%f}) AS b
        RETURN distance(a, b)""" % (a['lat'], a['lon'], b['lat'], b['lon'])

        distance = redis_graph.query(q).result_set[0][0]
        error_rate = 0.1 * expected_distance
        self.env.assertAlmostEqual(distance, expected_distance, error_rate)

    def test_point_distance(self):
        # 0 m apart
        a = {'lat': 32.070794860, 'lon': 34.820751118}
        expected_distance = 0
        self.assert_distance(a, a, expected_distance)

        # 160 m apart
        a = {'lat': 32.070794860, 'lon': 34.820751118}
        b = {'lat': 32.070109656, 'lon': 34.822351298}
        expected_distance = 160
        self.assert_distance(a, b, expected_distance)

        # 11352 km apart
        a = {'lat': 32.070794860, 'lon': 34.820751118}
        b = {'lat': 30.621734079, 'lon': -96.33775507}
        expected_distance = 11352120
        self.assert_distance(a, b, expected_distance)

    def test_point_values(self):
        try:
            # latitude > 90
            q = "RETURN point({latitude:90.1, longitude:20}) AS p"
            res = redis_graph.query(q)
            assert (False)
        except Exception as e:
            # Expecting an error.
            self.env.assertIn('latitude should be within', str(e))

        try:
            # latitude < -90
            q = "RETURN point({latitude:-90.1, longitude:20}) AS p"
            res = redis_graph.query(q)
            assert (False)
        except Exception as e:
            # Expecting an error.
            self.env.assertIn('latitude should be within', str(e))

        try:
            # longitude > 180
            q = "RETURN point({latitude:10, longitude:180.1}) AS p"
            res = redis_graph.query(q)
            assert (False)
        except Exception as e:
            # Expecting an error.
            self.env.assertIn('longitude should be within', str(e))

        try:
            # longitude < -180
            q = "RETURN point({latitude:10, longitude:-180.1}) AS p"
            res = redis_graph.query(q)
            assert (False)
        except Exception as e:
            # Expecting an error.
            self.env.assertIn('longitude should be within', str(e))

    def test_point_index_lookup(self):
        home = {'lat': 32.070794860, 'lon': 34.820751118}
        univ = {'lat': 30.621734079, 'lon': -96.33775507}
        kiosk = {'lat': 32.07011414663042, 'lon': 34.82235394761603}
        austin = {'lat': 30.274919961709788, 'lon': -97.7403239617543}
        miradouro = {'lat': 37.854010999507736, 'lon': -25.775820972037057}

        # create index over location
        q = "create index on :N(loc)"
        redis_graph.query(q)

        # create 2 points: 'home' and 'univ'
        q = """create (:N {name:'home', loc:point({ latitude:%f, longitude:%f })})""" % (
            home['lat'], home['lon'])
        redis_graph.query(q)
        q = """create (:N {name:'univ', loc:point({ latitude:%f, longitude:%f })})""" % (
            univ['lat'], univ['lon'])
        redis_graph.query(q)

        # validate that the entities were created and can be returned properly
        q = """match (n:N) RETURN n.name, n.loc ORDER BY n.name"""
        actual_result = redis_graph.query(q)
        self.env.assertEquals(actual_result.result_set[0][0], "home")
        self.env.assertAlmostEqual(actual_result.result_set[0][1]["latitude"],
                                   32.070794860, 1e-5)
        self.env.assertAlmostEqual(actual_result.result_set[0][1]["longitude"],
                                   34.820751118, 1e-5)

        self.env.assertEquals(actual_result.result_set[1][0], "univ")
        self.env.assertAlmostEqual(actual_result.result_set[1][1]["latitude"],
                                   30.621734079, 1e-5)
        self.env.assertAlmostEqual(actual_result.result_set[1][1]["longitude"],
                                   -96.33775507, 1e-5)

        idx_q = """MATCH (n:N) WHERE distance(n.loc, point({latitude:%f, longitude:%f})) < %d RETURN n.name"""
        none_idx_q = """MATCH (n) WHERE distance(n.loc, point({latitude:%f, longitude:%f})) < %d RETURN n.name"""

        # make sure index is being utilized
        plan = redis_graph.execution_plan(idx_q % (32.12, 43.32, 100))
        self.env.assertIn('Index Scan', plan)

        # near kiosk (200m)
        distance = 200
        idx_res = redis_graph.query(
            idx_q % (kiosk['lat'], kiosk['lon'], distance)).result_set
        none_idx_res = redis_graph.query(
            none_idx_q % (kiosk['lat'], kiosk['lon'], distance)).result_set

        # expecting just a single result: 'home'
        self.env.assertEquals(len(idx_res), 1)
        self.env.assertEquals(idx_res, none_idx_res)
        self.env.assertEquals(idx_res[0][0], 'home')

        # near "Miradouro do Cerrado das Freiras" (100km)
        # expecting no results
        distance = 100000
        idx_res = redis_graph.query(
            idx_q % (miradouro['lat'], miradouro['lon'], distance)).result_set
        none_idx_res = redis_graph.query(
            none_idx_q %
            (miradouro['lat'], miradouro['lon'], distance)).result_set
        self.env.assertEquals(idx_res, none_idx_res)
        self.env.assertEquals(len(idx_res), 0)

        # near Austin Texas (200km)
        # expecting just a single result: 'univ'
        distance = 200000
        idx_res = redis_graph.query(
            idx_q % (austin['lat'], austin['lon'], distance)).result_set
        none_idx_res = redis_graph.query(
            none_idx_q % (austin['lat'], austin['lon'], distance)).result_set
        self.env.assertEquals(idx_res, none_idx_res)
        self.env.assertEquals(len(idx_res), 1)
        self.env.assertEquals(idx_res[0][0], 'univ')
Esempio n. 5
0
class testPagerankFlow(FlowTestsBase):
    def __init__(self):
        self.env = Env(decodeResponses=True)
        global redis_graph
        redis_con = self.env.getConnection()
        redis_graph = Graph(GRAPH_ID, redis_con)

    def test_pagerank_no_label_no_relation(self):
        self.env.cmd('flushall')
        q = "CREATE (a:L0 {v:0})-[:R0]->(b:L1 {v:1})-[:R1]->(c:L2 {v:2})"
        redis_graph.query(q)
        q = """CALL algo.pageRank(NULL, NULL) YIELD node, score RETURN node.v, score"""
        resultset = redis_graph.query(q).result_set

        self.env.assertEqual(len(resultset), 3)
        self.env.assertEqual(resultset[0][0], 2)
        self.env.assertAlmostEqual(resultset[0][1], 0.609753012657166, 0.0001)
        self.env.assertEqual(resultset[1][0], 1)
        self.env.assertAlmostEqual(resultset[1][1], 0.286585807800293, 0.0001)
        self.env.assertEqual(resultset[2][0], 0)
        self.env.assertAlmostEqual(resultset[2][1], 0.103661172091961, 0.0001)

    def test_pagerank_no_label(self):
        self.env.cmd('flushall')
        q = "CREATE (a:L0 {v:0})-[:R]->(b:L1 {v:1})-[:R0]->(c:L2 {v:2})"
        redis_graph.query(q)
        q = """CALL algo.pageRank(NULL, 'R') YIELD node, score RETURN node.v, score"""
        resultset = redis_graph.query(q).result_set

        self.env.assertEqual(len(resultset), 3)
        self.env.assertEqual(resultset[0][0], 1)
        self.env.assertAlmostEqual(resultset[0][1], 0.660703718662262, 0.0001)
        self.env.assertEqual(resultset[1][0], 0)
        self.env.assertAlmostEqual(resultset[1][1], 0.169648125767708, 0.0001)
        self.env.assertEqual(resultset[2][0], 2)
        self.env.assertAlmostEqual(resultset[2][1], 0.169648125767708, 0.0001)

    def test_pagerank_no_relation(self):
        self.env.cmd('flushall')
        q = "CREATE (a:L {v:0})-[:R]->(b:L {v:1})-[:R0]->(c:L2 {v:2})"
        redis_graph.query(q)
        q = """CALL algo.pageRank('L', NULL) YIELD node, score RETURN node.v, score"""
        resultset = redis_graph.query(q).result_set

        self.env.assertEqual(len(resultset), 2)
        self.env.assertEqual(resultset[0][0], 1)
        self.env.assertAlmostEqual(resultset[0][1], 0.777813196182251, 0.0001)
        self.env.assertEqual(resultset[1][0], 0)
        self.env.assertAlmostEqual(resultset[1][1], 0.22218681871891, 0.0001)

    def test_pagerank_no_connections(self):
        # Pagerank only considers connections where both ends
        # are of the same type, as such it might happen that pagerank
        # is executed against an empty matrix.
        queries = [
            # No data, no edges with both src and dest of type 'L'
            "CREATE (a {v:1})-[:R]->(b {v:2})",
            "CREATE (a:L {v:1})-[:R]->(b {v:2})",
            "CREATE (a {v:1})-[:R]->(b:L {v:2})",
            "CREATE (a:L {v:1})-[:R]->(b {v:2})-[:R]->(c:L {v:3})",
        ]

        for q in queries:
            self.env.cmd('flushall')
            redis_graph.query(q)
            q = """CALL algo.pageRank('L', 'R') YIELD node, score RETURN node.v, score"""
            resultset = redis_graph.query(q).result_set

            self.env.assertEqual(len(resultset), 0)

    def test_pagerank(self):
        # Pagerank considers only nodes of given label and
        # relation of given relationship type
        # multiple edges between two nodes are considered as a single connection.
        queries = [
            # Single Label, single connection.
            "CREATE (a:L {v:1})-[:R]->(b:L {v:2})",
            # Single Label, multi connection.
            "CREATE (a:L {v:1})-[:R]->(b:L {v:2}), (a)-[:R]->(b)",
            # Multi Label, single connection.
            "CREATE (a:L {v:1})-[:R]->(b:L {v:2}), (:X)-[:R]->(:X)",
            # Multi Label, multi connection.
            "CREATE (a:L {v:1})-[:R]->(b:L {v:2}), (a)-[:R]->(b), (:X)-[:R]->(:X)"
        ]

        for q in queries:
            self.env.cmd('flushall')
            redis_graph.query(q)
            q = """CALL algo.pageRank('L', 'R') YIELD node, score RETURN node.v, score"""
            resultset = redis_graph.query(q).result_set

            # 2) 1) 1) (integer) 2
            # 2) "0.777813196182251"
            # 2) 1) (integer) 1
            # 2) "0.22218681871891"
            self.env.assertEqual(len(resultset), 2)
            self.env.assertEqual(resultset[0][0], 2)
            self.env.assertAlmostEqual(resultset[0][1], 0.777813196182251,
                                       0.0001)
            self.env.assertEqual(resultset[1][0], 1)
            self.env.assertAlmostEqual(resultset[1][1], 0.22218681871891,
                                       0.0001)
class TestAggregate():
    def __init__(self):
        self.env = Env()
        add_values(self.env)

    def testGroupBy(self):
        cmd = ['ft.aggregate', 'games', '*',
               'GROUPBY', '1', '@brand',
               'REDUCE', 'count', '0', 'AS', 'count',
               'SORTBY', 2, '@count', 'desc',
               'LIMIT', '0', '5'
               ]

        res = self.env.cmd(*cmd)
        self.env.assertIsNotNone(res)
        self.env.assertEqual([292L, ['brand', '', 'count', '1518'], ['brand', 'mad catz', 'count', '43'],
                                    ['brand', 'generic', 'count', '40'], ['brand', 'steelseries', 'count', '37'],
                                    ['brand', 'logitech', 'count', '35']], res)

    def testMinMax(self):
        cmd = ['ft.aggregate', 'games', 'sony',
               'GROUPBY', '1', '@brand',
               'REDUCE', 'count', '0',
               'REDUCE', 'min', '1', '@price', 'as', 'minPrice',
               'SORTBY', '2', '@minPrice', 'DESC']
        res = self.env.cmd(*cmd)
        self.env.assertIsNotNone(res)
        row = to_dict(res[1])
        self.env.assertEqual(88, int(float(row['minPrice'])))

        cmd = ['ft.aggregate', 'games', 'sony',
               'GROUPBY', '1', '@brand',
               'REDUCE', 'count', '0',
               'REDUCE', 'max', '1', '@price', 'as', 'maxPrice',
               'SORTBY', '2', '@maxPrice', 'DESC']
        res = self.env.cmd(*cmd)
        row = to_dict(res[1])
        self.env.assertEqual(695, int(float(row['maxPrice'])))

    def testAvg(self):
        cmd = ['ft.aggregate', 'games', 'sony',
               'GROUPBY', '1', '@brand',
               'REDUCE', 'avg', '1', '@price', 'AS', 'avg_price',
               'REDUCE', 'count', '0',
               'SORTBY', '2', '@avg_price', 'DESC']
        res = self.env.cmd(*cmd)
        self.env.assertIsNotNone(res)
        self.env.assertEqual(26, res[0])
        # Ensure the formatting actually exists

        first_row = to_dict(res[1])
        self.env.assertEqual(109, int(float(first_row['avg_price'])))

        for row in res[1:]:
            row = to_dict(row)
            self.env.assertIn('avg_price', row)

        # Test aliasing
        cmd = ['FT.AGGREGATE', 'games', 'sony', 'GROUPBY', '1', '@brand',
               'REDUCE', 'avg', '1', '@price', 'AS', 'avgPrice']
        res = self.env.cmd(*cmd)
        first_row = to_dict(res[1])
        self.env.assertEqual(17, int(float(first_row['avgPrice'])))

    def testCountDistinct(self):
        cmd = ['FT.AGGREGATE', 'games', '*',
               'GROUPBY', '1', '@brand',
               'REDUCE', 'COUNT_DISTINCT', '1', '@title', 'AS', 'count_distinct(title)',
               'REDUCE', 'COUNT', '0'
               ]
        res = self.env.cmd(*cmd)[1:]
        # print res
        row = to_dict(res[0])
        self.env.assertEqual(1484, int(row['count_distinct(title)']))

        cmd = ['FT.AGGREGATE', 'games', '*',
               'GROUPBY', '1', '@brand',
               'REDUCE', 'COUNT_DISTINCTISH', '1', '@title', 'AS', 'count_distinctish(title)',
               'REDUCE', 'COUNT', '0'
               ]
        res = self.env.cmd(*cmd)[1:]
        # print res
        row = to_dict(res[0])
        self.env.assertEqual(1461, int(row['count_distinctish(title)']))

    def testQuantile(self):
        cmd = ['FT.AGGREGATE', 'games', '*',
               'GROUPBY', '1', '@brand',
               'REDUCE', 'QUANTILE', '2', '@price', '0.50', 'AS', 'q50',
               'REDUCE', 'QUANTILE', '2', '@price', '0.90', 'AS', 'q90',
               'REDUCE', 'QUANTILE', '2', '@price', '0.95', 'AS', 'q95',
               'REDUCE', 'AVG', '1', '@price',
               'REDUCE', 'COUNT', '0', 'AS', 'rowcount',
               'SORTBY', '2', '@rowcount', 'DESC', 'MAX', '1']

        res = self.env.cmd(*cmd)
        row = to_dict(res[1])
        # TODO: Better samples
        self.env.assertAlmostEqual(14.99, float(row['q50']), delta=3)
        self.env.assertAlmostEqual(70, float(row['q90']), delta=50)

        # This tests the 95th percentile, which is error prone because
        # so few samples actually exist. I'm disabling it for now so that
        # there is no breakage in CI
        # self.env.assertAlmostEqual(110, (float(row['q95'])), delta=50)

    def testStdDev(self):
        cmd = ['FT.AGGREGATE', 'games', '*',
               'GROUPBY', '1', '@brand',
               'REDUCE', 'STDDEV', '1', '@price', 'AS', 'stddev(price)',
               'REDUCE', 'AVG', '1', '@price', 'AS', 'avgPrice',
               'REDUCE', 'QUANTILE', '2', '@price', '0.50', 'AS', 'q50Price',
               'REDUCE', 'COUNT', '0', 'AS', 'rowcount',
               'SORTBY', '2', '@rowcount', 'DESC',
               'LIMIT', '0', '10']
        res = self.env.cmd(*cmd)
        row = to_dict(res[1])

        self.env.assertTrue(10 <= int(
            float(row['q50Price'])) <= 20)
        self.env.assertAlmostEqual(53, int(float(row['stddev(price)'])), delta=50)
        self.env.assertEqual(29, int(float(row['avgPrice'])))

    def testParseTime(self):
        cmd = ['FT.AGGREGATE', 'games', '*',
               'GROUPBY', '1', '@brand',
               'REDUCE', 'COUNT', '0', 'AS', 'count',
               'APPLY', 'timefmt(1517417144)', 'AS', 'dt',
               'APPLY', 'parse_time("%FT%TZ", @dt)', 'as', 'parsed_dt',
               'LIMIT', '0', '1']
        res = self.env.cmd(*cmd)

        self.env.assertEqual(['brand', '', 'count', '1518', 'dt',
                              '2018-01-31T16:45:44Z', 'parsed_dt', '1517417144'], res[1])

    def testRandomSample(self):
        cmd = ['FT.AGGREGATE', 'games', '*', 'GROUPBY', '1', '@brand',
               'REDUCE', 'COUNT', '0', 'AS', 'num',
               'REDUCE', 'RANDOM_SAMPLE', '2', '@price', '10',
               'SORTBY', '2', '@num', 'DESC', 'MAX', '10']
        for row in self.env.cmd(*cmd)[1:]:
            self.env.assertIsInstance(row[5], list)
            self.env.assertGreater(len(row[5]), 0)
            self.env.assertGreaterEqual(row[3], len(row[5]))

            self.env.assertLessEqual(len(row[5]), 10)

    def testTimeFunctions(self):
        cmd = ['FT.AGGREGATE', 'games', '*',

               'APPLY', '1517417144', 'AS', 'dt',
               'APPLY', 'timefmt(@dt)', 'AS', 'timefmt',
               'APPLY', 'day(@dt)', 'AS', 'day',
               'APPLY', 'hour(@dt)', 'AS', 'hour',
               'APPLY', 'minute(@dt)', 'AS', 'minute',
               'APPLY', 'month(@dt)', 'AS', 'month',
               'APPLY', 'dayofweek(@dt)', 'AS', 'dayofweek',
               'APPLY', 'dayofmonth(@dt)', 'AS', 'dayofmonth',
               'APPLY', 'dayofyear(@dt)', 'AS', 'dayofyear',
               'APPLY', 'year(@dt)', 'AS', 'year',

               'LIMIT', '0', '1']
        res = self.env.cmd(*cmd)
        self.env.assertListEqual([1L, ['dt', '1517417144', 'timefmt', '2018-01-31T16:45:44Z', 'day', '1517356800', 'hour', '1517414400',
                                       'minute', '1517417100', 'month', '1514764800', 'dayofweek', '3', 'dayofmonth', '31', 'dayofyear', '30', 'year', '2018']], res)

    def testStringFormat(self):
        cmd = ['FT.AGGREGATE', 'games', '@brand:sony',
               'GROUPBY', '2', '@title', '@brand',
               'REDUCE', 'COUNT', '0',
               'REDUCE', 'MAX', '1', '@price', 'AS', 'price',
               'APPLY', 'format("%s|%s|%s|%s", @title, @brand, "Mark", @price)', 'as', 'titleBrand',
               'LIMIT', '0', '10']
        res = self.env.cmd(*cmd)
        for row in res[1:]:
            row = to_dict(row)
            expected = '%s|%s|%s|%g' % (
                row['title'], row['brand'], 'Mark', float(row['price']))
            self.env.assertEqual(expected, row['titleBrand'])

    def testSum(self):
        cmd = ['ft.aggregate', 'games', '*',
               'GROUPBY', '1', '@brand',
               'REDUCE', 'count', '0', 'AS', 'count',
               'REDUCE', 'sum', 1, '@price', 'AS', 'sum(price)',
               'SORTBY', 2, '@sum(price)', 'desc',
               'LIMIT', '0', '5'
               ]
        res = self.env.cmd(*cmd)
        self.env.assertEqual([292L, ['brand', '', 'count', '1518', 'sum(price)', '44780.69'],
                             ['brand', 'mad catz', 'count',
                                 '43', 'sum(price)', '3973.48'],
                             ['brand', 'razer', 'count', '26',
                                 'sum(price)', '2558.58'],
                             ['brand', 'logitech', 'count',
                                 '35', 'sum(price)', '2329.21'],
                             ['brand', 'steelseries', 'count', '37', 'sum(price)', '1851.12']], res)

    def testFilter(self):
        cmd = ['ft.aggregate', 'games', '*',
               'GROUPBY', '1', '@brand',
               'REDUCE', 'count', '0', 'AS', 'count',
               'FILTER', '@count > 5'
               ]

        res = self.env.cmd(*cmd)
        for row in res[1:]:
            row = to_dict(row)
            self.env.assertGreater(int(row['count']), 5)

        cmd = ['ft.aggregate', 'games', '*',
               'GROUPBY', '1', '@brand',
               'REDUCE', 'count', '0', 'AS', 'count',
               'FILTER', '@count < 5',
               'FILTER', '@count > 2 && @brand != ""'
               ]

        res = self.env.cmd(*cmd)
        for row in res[1:]:
            row = to_dict(row)
            self.env.assertLess(int(row['count']), 5)
            self.env.assertGreater(int(row['count']), 2)

    def testToList(self):
        cmd = ['ft.aggregate', 'games', '*',
               'GROUPBY', '1', '@brand',
               'REDUCE', 'count_distinct', '1', '@price', 'as', 'count',
               'REDUCE', 'tolist', 1, '@price', 'as', 'prices',
               'SORTBY', 2, '@count', 'desc',
               'LIMIT', '0', '5'
               ]
        res = self.env.cmd(*cmd)

        for row in res[1:]:
            row = to_dict(row)
            self.env.assertEqual(int(row['count']), len(row['prices']))

    def testSortBy(self):
        res = self.env.cmd('ft.aggregate', 'games', '*', 'GROUPBY', '1', '@brand',
                           'REDUCE', 'sum', 1, '@price', 'as', 'price',
                           'SORTBY', 2, '@price', 'desc',
                           'LIMIT', '0', '2')

        self.env.assertListEqual([292L, ['brand', '', 'price', '44780.69'], [
                                 'brand', 'mad catz', 'price', '3973.48']], res)

        res = self.env.cmd('ft.aggregate', 'games', '*', 'GROUPBY', '1', '@brand',
                           'REDUCE', 'sum', 1, '@price', 'as', 'price',
                           'SORTBY', 2, '@price', 'asc',
                           'LIMIT', '0', '2')

        self.env.assertListEqual([292L, ['brand', 'myiico', 'price', '0.23'], [
                                 'brand', 'crystal dynamics', 'price', '0.25']], res)

        # Test MAX with limit higher than it
        res = self.env.cmd('ft.aggregate', 'games', '*', 'GROUPBY', '1', '@brand',
                           'REDUCE', 'sum', 1, '@price', 'as', 'price',
                           'SORTBY', 2, '@price', 'asc', 'MAX', 2)
        
        self.env.assertListEqual([292L, ['brand', 'myiico', 'price', '0.23'], [
                                 'brand', 'crystal dynamics', 'price', '0.25']], res)

        # Test Sorting by multiple properties
        res = self.env.cmd('ft.aggregate', 'games', '*', 'GROUPBY', '1', '@brand',
                           'REDUCE', 'sum', 1, '@price', 'as', 'price',
                           'APPLY', '(@price % 10)', 'AS', 'price',
                           'SORTBY', 4, '@price', 'asc', '@brand', 'desc', 'MAX', 10,
                           )
        self.env.assertListEqual([292L, ['brand', 'zps', 'price', '0'], ['brand', 'zalman', 'price', '0'], ['brand', 'yoozoo', 'price', '0'], ['brand', 'white label', 'price', '0'], ['brand', 'stinky', 'price', '0'], [
                                 'brand', 'polaroid', 'price', '0'], ['brand', 'plantronics', 'price', '0'], ['brand', 'ozone', 'price', '0'], ['brand', 'oooo', 'price', '0'], ['brand', 'neon', 'price', '0']], res)

    def testExpressions(self):
        pass

    def testNoGroup(self):
        res = self.env.cmd('ft.aggregate', 'games', '*', 'LOAD', '2', '@brand', '@price',
                           'APPLY', 'floor(sqrt(@price)) % 10', 'AS', 'price',
                           'SORTBY', 4, '@price', 'desc', '@brand', 'desc', 'MAX', 5,
                           )
        exp = [2265L,
 ['brand', 'xbox', 'price', '9'],
 ['brand', 'turtle beach', 'price', '9'],
 ['brand', 'trust', 'price', '9'],
 ['brand', 'steelseries', 'price', '9'],
 ['brand', 'speedlink', 'price', '9']]
        # exp = [2265L, ['brand', 'Xbox', 'price', '9'], ['brand', 'Turtle Beach', 'price', '9'], [
                            #  'brand', 'Trust', 'price', '9'], ['brand', 'SteelSeries', 'price', '9'], ['brand', 'Speedlink', 'price', '9']]
        self.env.assertListEqual(exp[1], res[1])

    def testLoad(self):
        res = self.env.cmd('ft.aggregate', 'games', '*',
                           'LOAD', '3', '@brand', '@price', '@nonexist',
                           'SORTBY', 2, '@price', 'DESC', 'MAX', 2)
        exp = [3L, ['brand', '', 'price', '759.12'], ['brand', 'Sony', 'price', '695.8']]
        self.env.assertEqual(exp[1], res[1])

    def testSplit(self):
        res = self.env.cmd('ft.aggregate', 'games', '*', 'APPLY', 'split("hello world,  foo,,,bar,", ",", " ")', 'AS', 'strs',
                           'APPLY', 'split("hello world,  foo,,,bar,", " ", ",")', 'AS', 'strs2',
                           'APPLY', 'split("hello world,  foo,,,bar,", "", "")', 'AS', 'strs3',
                           'APPLY', 'split("hello world,  foo,,,bar,")', 'AS', 'strs4',
                           'APPLY', 'split("hello world,  foo,,,bar,",",")', 'AS', 'strs5',
                           'APPLY', 'split("")', 'AS', 'empty',
                           'LIMIT', '0', '1'
                           )
        # print "Got {} results".format(len(res))
        # return
        # pprint.pprint(res)
        self.env.assertListEqual([1L, ['strs', ['hello world', 'foo', 'bar'],
                                       'strs2', ['hello', 'world', 'foo,,,bar'],
                                       'strs3', ['hello world,  foo,,,bar,'],
                                       'strs4', ['hello world', 'foo', 'bar'],
                                       'strs5', ['hello world', 'foo', 'bar'],
                                       'empty', []]], res)

    def testFirstValue(self):
        res = self.env.cmd('ft.aggregate', 'games', '@brand:(sony|matias|beyerdynamic|(mad catz))',
                           'GROUPBY', 1, '@brand',
                           'REDUCE', 'FIRST_VALUE', 4, '@title', 'BY', '@price', 'DESC', 'AS', 'top_item',
                           'REDUCE', 'FIRST_VALUE', 4, '@price', 'BY', '@price', 'DESC', 'AS', 'top_price',
                           'REDUCE', 'FIRST_VALUE', 4, '@title', 'BY', '@price', 'ASC', 'AS', 'bottom_item',
                           'REDUCE', 'FIRST_VALUE', 4, '@price', 'BY', '@price', 'ASC', 'AS', 'bottom_price',
                           'SORTBY', 2, '@top_price', 'DESC', 'MAX', 5
                           )
        expected = [4L, ['brand', 'sony', 'top_item', 'sony psp slim &amp; lite 2000 console', 'top_price', '695.8', 'bottom_item', 'sony dlchd20p high speed hdmi cable for playstation 3', 'bottom_price', '5.88'],
                                 ['brand', 'matias', 'top_item', 'matias halfkeyboard usb', 'top_price',
                                     '559.99', 'bottom_item', 'matias halfkeyboard usb', 'bottom_price', '559.99'],
                                 ['brand', 'beyerdynamic', 'top_item', 'beyerdynamic mmx300 pc gaming premium digital headset with microphone', 'top_price', '359.74',
                                     'bottom_item', 'beyerdynamic headzone pc gaming digital surround sound system with mmx300 digital headset with microphone', 'bottom_price', '0'],
                                 ['brand', 'mad catz', 'top_item', 'mad catz s.t.r.i.k.e.7 gaming keyboard', 'top_price', '295.95', 'bottom_item', 'madcatz mov4545 xbox replacement breakaway cable', 'bottom_price', '3.49']]
        self.env.assertListEqual(expected, res)

    def testLoadAfterGroupBy(self):
        with self.env.assertResponseError():
            self.env.cmd('ft.aggregate', 'games', '*',
                         'GROUPBY', 1, '@brand',
                         'LOAD', 1, '@brand')
class test_torch_script_extesions:
    def __init__(self):
        self.env = Env()
        if not TEST_PT:
            self.env.debugPrint("skipping {} since TEST_PT=0".format(
                sys._getframe().f_code.co_name),
                                force=True)
            self.env.skip()

        self.con = self.env.getConnection()
        test_data_path = os.path.join(os.path.dirname(__file__), 'test_data')
        script_filename = os.path.join(test_data_path, 'redis_scripts.py')
        with open(script_filename, 'rb') as f:
            script = f.read()

        ret = self.con.execute_command('AI.SCRIPTSET', 'redis_scripts{1}',
                                       DEVICE, 'SOURCE', script)
        self.env.assertEqual(ret, b'OK')
        # self.env.ensureSlaveSynced(self.con, self.env)

    def test_redis_error(self):
        try:
            self.con.execute_command('AI.SCRIPTEXECUTE', 'redis_scripts',
                                     'test_redis_error', 'KEYS', 1, "x{1}",
                                     "INPUTS", 1, "x{1}")
            self.env.assertTrue(False)
        except:
            pass

    def test_simple_test_set(self):
        self.con.execute_command('AI.SCRIPTEXECUTE', 'redis_scripts{1}',
                                 'test_set_key', 'KEYS', 1, "x{1}", "INPUTS",
                                 2, "x{1}", 1)
        self.env.assertEqual(b"1", self.con.get("x{1}"))

    def test_int_set_get(self):
        self.con.execute_command('AI.SCRIPTEXECUTE', 'redis_scripts{1}',
                                 'test_int_set_get', 'KEYS', 1, "x{1}",
                                 "INPUTS", 2, "x{1}", 1, 'OUTPUTS', 1, 'y{1}')
        y = self.con.execute_command('AI.TENSORGET', 'y{1}', 'meta', 'VALUES')
        self.env.assertEqual(
            y, [b"dtype", b"INT64", b"shape", [], b"values", [1]])

    def test_int_set_incr(self):
        self.con.execute_command('AI.SCRIPTEXECUTE', 'redis_scripts{1}',
                                 'test_int_set_incr', 'KEYS', 1, "x{1}",
                                 "INPUTS", 2, "x{1}", 1, 'OUTPUTS', 1, 'y{1}')
        y = self.con.execute_command('AI.TENSORGET', 'y{1}', 'meta', 'VALUES')
        self.env.assertEqual(
            y, [b"dtype", b"INT64", b"shape", [], b"values", [2]])

    def test_float_get_set(self):
        self.con.execute_command('AI.SCRIPTEXECUTE', 'redis_scripts{1}',
                                 'test_float_set_get', 'KEYS', 1, "x{1}",
                                 "INPUTS", 2, "x{1}", 1.1, 'OUTPUTS', 1,
                                 'y{1}')
        y = self.con.execute_command('AI.TENSORGET', 'y{1}', 'meta', 'VALUES')
        self.env.assertEqual(y[0], b"dtype")
        self.env.assertEqual(y[1], b"FLOAT")
        self.env.assertEqual(y[2], b"shape")
        self.env.assertEqual(y[3], [])
        self.env.assertEqual(y[4], b"values")
        self.env.assertAlmostEqual(float(y[5][0]), 1.1, 0.1)

    def test_int_list(self):
        self.con.execute_command('AI.SCRIPTEXECUTE', 'redis_scripts{1}',
                                 'test_int_list', 'KEYS', 1, "int_list{1}",
                                 'INPUTS', 1, "int_list{1}", "LIST_INPUTS", 2,
                                 "1", "2", 'OUTPUTS', 1, 'y{1}')
        y = self.con.execute_command('AI.TENSORGET', 'y{1}', 'meta', 'VALUES')
        self.env.assertEqual(
            y, [b"dtype", b"INT64", b"shape", [2, 1], b"values", [1, 2]])

    def test_str_list(self):
        self.con.execute_command('AI.SCRIPTEXECUTE', 'redis_scripts{1}',
                                 'test_str_list', 'KEYS', 1, "str_list{1}",
                                 'INPUTS', 1, "str_list{1}", "LIST_INPUTS", 2,
                                 "1", "2")
        res = self.con.execute_command("LRANGE", "str_list{1}", "0", "2")
        self.env.assertEqual(res, [b"1", b"2"])

    def test_hash(self):
        self.con.execute_command('AI.SCRIPTEXECUTE', 'redis_scripts{1}',
                                 'test_hash', 'KEYS', 1, "hash{1}", 'INPUTS',
                                 1, "hash{1}", "LIST_INPUTS", 4, "field1", 1,
                                 "field2", 2, 'OUTPUTS', 1, 'y{1}')
        y = self.con.execute_command('AI.TENSORGET', 'y{1}', 'meta', 'VALUES')
        self.env.assertEqual(
            y, [b"dtype", b"INT64", b"shape", [2, 1], b"values", [1, 2]])