Skip to content

Commit

Permalink
Merge pull request #377 from utopia-php/contains-v2
Browse files Browse the repository at this point in the history
Contains  query v2
  • Loading branch information
abnegate authored Jan 19, 2024
2 parents 745eedf + 75b75b0 commit e6a7632
Show file tree
Hide file tree
Showing 25 changed files with 935 additions and 332 deletions.
3 changes: 0 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,9 @@ mock.json
data-tests.php
loader.php
.phpunit.result.cache
/bin/view/results/
.vscode
.vscode/*
database.sql

## - Oh Wess!
Makefile
.envrc
.vscode
Expand Down
3 changes: 2 additions & 1 deletion bin/cli.php
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
<?php

// require_once __DIR__.'/init.php';
require_once '/usr/src/code/vendor/autoload.php';

use Utopia\CLI\CLI;

ini_set('memory_limit', '-1');

$cli = new CLI();

include 'tasks/load.php';
Expand Down
20 changes: 10 additions & 10 deletions bin/tasks/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@

/**
* @Example
* docker-compose exec tests bin/index --adapter=mysql --name=testing
* docker compose exec tests bin/index --adapter=mysql --name=testing
*/

$cli
->task('index')
->desc('Index mock data for testing queries')
->param('adapter', '', new Text(0), 'Database adapter', false)
->param('name', '', new Text(0), 'Name of created database.', false)
->param('adapter', '', new Text(0), 'Database adapter')
->param('name', '', new Text(0), 'Name of created database.')
->action(function ($adapter, $name) {
$namespace = '_ns';
$cache = new Cache(new NoCache());
Expand Down Expand Up @@ -74,36 +74,36 @@
$database->setDatabase($name);
$database->setNamespace($namespace);

Console::info("For query: greaterThan(created, 2010-01-01 05:00:00)', 'equal(genre,travel)");

Console::info("greaterThan('created', ['2010-01-01 05:00:00']), equal('genre', ['travel'])");
$start = microtime(true);
$database->createIndex('articles', 'createdGenre', Database::INDEX_KEY, ['created', 'genre'], [], [Database::ORDER_DESC, Database::ORDER_DESC]);
$time = microtime(true) - $start;
Console::success("{$time} seconds");

Console::info("equal('genre', ['fashion', 'finance', 'sports'])");

$start = microtime(true);
$database->createIndex('articles', 'genre', Database::INDEX_KEY, ['genre'], [], [Database::ORDER_ASC]);
$time = microtime(true) - $start;
Console::success("{$time} seconds");


Console::info("greaterThan('views', 100000)");

$start = microtime(true);
$database->createIndex('articles', 'views', Database::INDEX_KEY, ['views'], [], [Database::ORDER_DESC]);
$time = microtime(true) - $start;
Console::success("{$time} seconds");


Console::info("search('text', 'Alice')");
$start = microtime(true);
$database->createIndex('articles', 'fulltextsearch', Database::INDEX_FULLTEXT, ['text']);
$time = microtime(true) - $start;
Console::success("{$time} seconds");
});

Console::info("contains('tags', ['tag1'])");
$start = microtime(true);
$database->createIndex('articles', 'tags', Database::INDEX_KEY, ['tags']);
$time = microtime(true) - $start;
Console::success("{$time} seconds");
});

$cli
->error()
Expand Down
23 changes: 13 additions & 10 deletions bin/tasks/load.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@

/**
* @Example
* docker-compose exec tests bin/load --adapter=mariadb --limit=1000 --name=testing
* docker compose exec tests bin/load --adapter=mariadb --limit=1000 --name=testing
*/

$cli
Expand All @@ -44,6 +44,7 @@
Console::info("Filling {$adapter} with {$limit} records: {$name}");

Swoole\Runtime::enableCoroutine();

switch ($adapter) {
case 'mariadb':
Co\run(function () use (&$start, $limit, $name, $namespace, $cache) {
Expand Down Expand Up @@ -85,7 +86,7 @@

// A coroutine is assigned per 1000 documents
for ($i = 0; $i < $limit / 1000; $i++) {
go(function () use ($pool, $faker, $name, $cache, $namespace) {
\go(function () use ($pool, $faker, $name, $cache, $namespace) {
$pdo = $pool->get();

$database = new Database(new MariaDB($pdo), $cache);
Expand All @@ -94,7 +95,7 @@

// Each coroutine loads 1000 documents
for ($i = 0; $i < 1000; $i++) {
addArticle($database, $faker);
createDocument($database, $faker);
}

// Reclaim resources
Expand Down Expand Up @@ -146,7 +147,7 @@

// A coroutine is assigned per 1000 documents
for ($i = 0; $i < $limit / 1000; $i++) {
go(function () use ($pool, $faker, $name, $cache, $namespace) {
\go(function () use ($pool, $faker, $name, $cache, $namespace) {
$pdo = $pool->get();

$database = new Database(new MySQL($pdo), $cache);
Expand All @@ -155,7 +156,7 @@

// Each coroutine loads 1000 documents
for ($i = 0; $i < 1000; $i++) {
addArticle($database, $faker);
createDocument($database, $faker);
}

// Reclaim resources
Expand Down Expand Up @@ -197,7 +198,7 @@

// Each coroutine loads 1000 documents
for ($i = 0; $i < 1000; $i++) {
addArticle($database, $faker);
createDocument($database, $faker);
}

$database = null;
Expand Down Expand Up @@ -233,25 +234,26 @@ function createSchema(Database $database): void
$database->create();

Authorization::setRole(Role::any()->toString());

$database->createCollection('articles', permissions: [
Permission::create(Role::any()),
Permission::read(Role::any()),
]);

$database->createAttribute('articles', 'author', Database::VAR_STRING, 256, true);
$database->createAttribute('articles', 'created', Database::VAR_DATETIME, 0, true, null, false, false, null, [], ['datetime']);
$database->createAttribute('articles', 'created', Database::VAR_DATETIME, 0, true, filters: ['datetime']);
$database->createAttribute('articles', 'text', Database::VAR_STRING, 5000, true);
$database->createAttribute('articles', 'genre', Database::VAR_STRING, 256, true);
$database->createAttribute('articles', 'views', Database::VAR_INTEGER, 0, true);
$database->createAttribute('articles', 'tags', Database::VAR_STRING, 0, true, array: true);
$database->createIndex('articles', 'text', Database::INDEX_FULLTEXT, ['text']);
}

function addArticle($database, Generator $faker): void
function createDocument($database, Generator $faker): void
{
$database->createDocument('articles', new Document([
// Five random users out of 10,000 get read access
// Three random users out of 10,000 get mutate access

'$permissions' => [
Permission::read(Role::any()),
Permission::read(Role::user($faker->randomNumber(9))),
Expand All @@ -272,6 +274,7 @@ function addArticle($database, Generator $faker): void
'created' => \Utopia\Database\DateTime::format($faker->dateTime()),
'text' => $faker->realTextBetween(1000, 4000),
'genre' => $faker->randomElement(['fashion', 'food', 'travel', 'music', 'lifestyle', 'fitness', 'diy', 'sports', 'finance']),
'views' => $faker->randomNumber(6)
'views' => $faker->randomNumber(6),
'tags' => $faker->randomElements(['short', 'quick', 'easy', 'medium', 'hard'], $faker->numberBetween(1, 5)),
]));
}
79 changes: 39 additions & 40 deletions bin/tasks/query.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@

/**
* @Example
* docker-compose exec tests bin/query --adapter=mariadb --limit=1000 --name=testing
* docker compose exec tests bin/query --adapter=mariadb --limit=1000 --name=testing
*/
$cli
->task('query')
->desc('Query mock data')
->param('adapter', '', new Text(0), 'Database adapter', false)
->param('name', '', new Text(0), 'Name of created database.', false)
->param('adapter', '', new Text(0), 'Database adapter')
->param('name', '', new Text(0), 'Name of created database.')
->param('limit', 25, new Numeric(), 'Limit on queried documents', true)
->action(function (string $adapter, string $name, int $limit) {
$namespace = '_ns';
Expand Down Expand Up @@ -80,113 +80,112 @@
return;
}


$faker = Factory::create();

$report = [];

$count = addRoles($faker, 1);
$count = setRoles($faker, 1);
Console::info("\n{$count} roles:");
$report[] = [
'roles' => $count,
'results' => runQueries($database, $limit)
];

$count = addRoles($faker, 100);
$count = setRoles($faker, 100);
Console::info("\n{$count} roles:");
$report[] = [
'roles' => $count,
'results' => runQueries($database, $limit)
];

$count = addRoles($faker, 400);
$count = setRoles($faker, 400);
Console::info("\n{$count} roles:");
$report[] = [
'roles' => $count,
'results' => runQueries($database, $limit)
];

$count = addRoles($faker, 500);
$count = setRoles($faker, 500);
Console::info("\n{$count} roles:");
$report[] = [
'roles' => $count,
'results' => runQueries($database, $limit)
];

$count = addRoles($faker, 1000);
$count = setRoles($faker, 1000);
Console::info("\n{$count} roles:");
$report[] = [
'roles' => $count,
'results' => runQueries($database, $limit)
];

if (!file_exists('bin/view/results')) {
mkdir('bin/view/results', 0777, true);
\mkdir('bin/view/results', 0777, true);
}

$time = time();
$f = fopen("bin/view/results/{$adapter}_{$name}_{$limit}_{$time}.json", 'w');
fwrite($f, json_encode($report));
fclose($f);
$time = \time();
$results = \fopen("bin/view/results/{$adapter}_{$name}_{$limit}_{$time}.json", 'w');
\fwrite($results, \json_encode($report));
\fclose($results);
});


$cli
->error()
->inject('error')
->action(function (Exception $error) {
Console::error($error->getMessage());
});
->error()
->inject('error')
->action(function (Exception $error) {
Console::error($error->getMessage());
});

function setRoles($faker, $count): int
{
for ($i = 0; $i < $count; $i++) {
Authorization::setRole($faker->numerify('user####'));
}
return \count(Authorization::getRoles());
}

function runQueries(Database $database, int $limit)
function runQueries(Database $database, int $limit): array
{
$results = [];
// Recent travel blogs

$results[] = runQuery([
// Recent travel blogs
$results["Querying greater than, equal[1] and limit"] = runQuery([
Query::greaterThan('created', '2010-01-01 05:00:00'),
Query::equal('genre', ['travel']),
Query::limit($limit)
], $database);

// Favorite genres

$results[] = runQuery([
$results["Querying equal[3] and limit"] = runQuery([
Query::equal('genre', ['fashion', 'finance', 'sports']),
Query::limit($limit)
], $database);

// Popular posts

$results[] = runQuery([
$results["Querying greaterThan, limit({$limit})"] = runQuery([
Query::greaterThan('views', 100000),
Query::limit($limit)
], $database);

// Fulltext search

$results[] = runQuery([
$results["Query search, limit({$limit})"] = runQuery([
Query::search('text', 'Alice'),
Query::limit($limit)
], $database);

return $results;
}
// Tags contain query
$results["Querying contains[1], limit({$limit})"] = runQuery([
Query::contains('tags', ['tag1']),
Query::limit($limit)
], $database);

function addRoles($faker, $count)
{
for ($i = 0; $i < $count; $i++) {
Authorization::setRole($faker->numerify('user####'));
}
return count(Authorization::getRoles());
return $results;
}

function runQuery(array $query, Database $database)
{
$info = array_map(function ($q) {
/** @var $q Query */
return $q->getAttribute() . ' : ' . $q->getMethod() . ' : ' . implode(',', $q->getValues());
$info = array_map(function (Query $q) {
return $q->getAttribute() . ': ' . $q->getMethod() . ' = ' . implode(',', $q->getValues());
}, $query);

Console::log('Running query: [' . implode(', ', $info) . ']');
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[{"roles":2,"results":[0.004142045974731445,0.0007698535919189453,0.0006570816040039062,4.3037660121917725]},{"roles":102,"results":[0.0031499862670898438,0.0012857913970947266,0.0013210773468017578,4.130218029022217]},{"roles":491,"results":[0.4965331554412842,0.36292195320129395,0.30788612365722656,4.9501330852508545]},{"roles":964,"results":[0.44646310806274414,0.44009995460510254,0.37430691719055176,4.239892959594727]},{"roles":1829,"results":[0.6837189197540283,1.6691820621490479,1.3487520217895508,98.95817399024963]}]
Loading

0 comments on commit e6a7632

Please sign in to comment.