Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make json objects in database searchable #22

Merged
merged 5 commits into from
Oct 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions lib/Controller/ObjectsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public function __construct(

/**
* Returns the template of the main app's page
*
*
* This method renders the main page of the application, adding any necessary data to the template.
*
* @NoAdminRequired
Expand All @@ -42,17 +42,17 @@ public function __construct(
* @return TemplateResponse The rendered template response
*/
public function page(): TemplateResponse
{
{
return new TemplateResponse(
'openconnector',
'index',
[]
);
}

/**
* Retrieves a list of all objects
*
*
* This method returns a JSON response containing an array of all objects in the system.
*
* @NoAdminRequired
Expand All @@ -69,12 +69,12 @@ public function index(ObjectService $objectService, SearchService $searchService
$searchConditions = $searchService->createMySQLSearchConditions(filters: $filters, fieldsToSearch: $fieldsToSearch);
$filters = $searchService->unsetSpecialQueryParams(filters: $filters);

return new JSONResponse(['results' => $this->objectEntityMapper->findAll(limit: null, offset: null, filters: $filters, searchConditions: $searchConditions, searchParams: $searchParams)]);
return new JSONResponse(['results' => $this->objectEntityMapper->findAll(filters: $filters, searchConditions: $searchConditions, searchParams: $searchParams)]);
}

/**
* Retrieves a single object by its ID
*
*
* This method returns a JSON response containing the details of a specific object.
*
* @NoAdminRequired
Expand All @@ -94,7 +94,7 @@ public function show(string $id): JSONResponse

/**
* Creates a new object
*
*
* This method creates a new object based on POST data.
*
* @NoAdminRequired
Expand All @@ -111,17 +111,17 @@ public function create(): JSONResponse
unset($data[$key]);
}
}

if (isset($data['id'])) {
unset($data['id']);
}

return new JSONResponse($this->objectEntityMapper->createFromArray(object: $data));
}

/**
* Updates an existing object
*
*
* This method updates an existing object based on its ID.
*
* @NoAdminRequired
Expand All @@ -147,7 +147,7 @@ public function update(int $id): JSONResponse

/**
* Deletes an object
*
*
* This method deletes an object based on its ID.
*
* @NoAdminRequired
Expand All @@ -162,4 +162,4 @@ public function destroy(int $id): JSONResponse

return new JSONResponse([]);
}
}
}
20 changes: 11 additions & 9 deletions lib/Db/ObjectEntity.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,16 @@ public function hydrate(array $object): self

public function jsonSerialize(): array
{
return [
'id' => $this->id,
'uuid' => $this->uuid,
'register' => $this->register,
'schema' => $this->schema,
'object' => $this->object,
'updated' => isset($this->updated) ? $this->updated->format('c') : null,
'created' => isset($this->created) ? $this->created->format('c') : null
];
// return [
// 'id' => $this->id,
// 'uuid' => $this->uuid,
// 'register' => $this->register,
// 'schema' => $this->schema,
// 'object' => $this->object,
// 'updated' => isset($this->updated) ? $this->updated->format('c') : null,
// 'created' => isset($this->created) ? $this->created->format('c') : null
// ];

return $this->object;
}
}
84 changes: 80 additions & 4 deletions lib/Db/ObjectEntityMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@

namespace OCA\OpenRegister\Db;

use Doctrine\DBAL\Platforms\MySQLPlatform;
use OCA\OpenRegister\Db\ObjectEntity;
use OCA\OpenRegister\Db\Register;
use OCA\OpenRegister\Db\Schema;
use OCA\OpenRegister\Service\IDatabaseJsonService;
use OCA\OpenRegister\Service\MySQLJsonService;
use OCP\AppFramework\Db\Entity;
use OCP\AppFramework\Db\QBMapper;
use OCP\DB\QueryBuilder\IQueryBuilder;
Expand All @@ -13,9 +16,17 @@

class ObjectEntityMapper extends QBMapper
{
public function __construct(IDBConnection $db)
private IDatabaseJsonService $databaseJsonService;

public const MAIN_FILTERS = ['register', 'schema', 'uuid', 'created', 'updated'];

public function __construct(IDBConnection $db, MySQLJsonService $mySQLJsonService)
{
parent::__construct($db, 'openregister_objects');

if($db->getDatabasePlatform() instanceof MySQLPlatform === true) {
$this->databaseJsonService = $mySQLJsonService;
}
}

/**
Expand Down Expand Up @@ -89,6 +100,37 @@ public function findByRegisterAndSchema(string $register, string $schema): Objec
return $this->findEntities(query: $qb);
}

public function countAll(?array $filters = [], ?array $searchConditions = [], ?array $searchParams = []): int
{
$qb = $this->db->getQueryBuilder();

$qb->selectAlias(select: $qb->createFunction(call: 'count(id)'), alias: 'count')
->from(from: 'openregister_objects');
foreach ($filters as $filter => $value) {
if ($value === 'IS NOT NULL' && in_array(needle: $filter, haystack: self::MAIN_FILTERS) === true) {
$qb->andWhere($qb->expr()->isNotNull($filter));
} elseif ($value === 'IS NULL' && in_array(needle: $filter, haystack: self::MAIN_FILTERS) === true) {
$qb->andWhere($qb->expr()->isNull($filter));
} else if (in_array(needle: $filter, haystack: self::MAIN_FILTERS) === true) {
$qb->andWhere($qb->expr()->eq($filter, $qb->createNamedParameter($value)));
}
}

if (!empty($searchConditions)) {
$qb->andWhere('(' . implode(' OR ', $searchConditions) . ')');
foreach ($searchParams as $param => $value) {
$qb->setParameter($param, $value);
}
}
$qb = $this->databaseJsonService->filterJson($qb, $filters);

$result = $qb->executeQuery();

$count = $result->fetchAll()[0]['count'];

return $count;
}

/**
* Find all ObjectEntitys
*
Expand All @@ -109,11 +151,11 @@ public function findAll(?int $limit = null, ?int $offset = null, ?array $filters
->setFirstResult($offset);

foreach ($filters as $filter => $value) {
if ($value === 'IS NOT NULL') {
if ($value === 'IS NOT NULL' && in_array(needle: $filter, haystack: self::MAIN_FILTERS) === true) {
$qb->andWhere($qb->expr()->isNotNull($filter));
} elseif ($value === 'IS NULL') {
} elseif ($value === 'IS NULL' && in_array(needle: $filter, haystack: self::MAIN_FILTERS) === true) {
$qb->andWhere($qb->expr()->isNull($filter));
} else {
} else if (in_array(needle: $filter, haystack: self::MAIN_FILTERS) === true) {
$qb->andWhere($qb->expr()->eq($filter, $qb->createNamedParameter($value)));
}
}
Expand All @@ -124,6 +166,8 @@ public function findAll(?int $limit = null, ?int $offset = null, ?array $filters
$qb->setParameter($param, $value);
}
}
$qb = $this->databaseJsonService->filterJson($qb, $filters);


return $this->findEntities(query: $qb);
}
Expand All @@ -148,4 +192,36 @@ public function updateFromArray(int $id, array $object): ObjectEntity

return $this->update($obj);
}

public function getFacets(array $filters = [])
{
if(key_exists(key: 'register', array: $filters) === true) {
$register = $filters['register'];
}
if(key_exists(key: 'schema', array: $filters) === true) {
$schema = $filters['schema'];
}

$fields = [];
if(isset($filters['_queries'])) {
$fields = $filters['_queries'];
}

unset(
$filters['_fields'],
$filters['register'],
$filters['schema'],
$filters['created'],
$filters['updated'],
$filters['uuid']
);

return $this->databaseJsonService->getAggregations(
builder: $this->db->getQueryBuilder(),
fields: $fields,
register: $register,
schema: $schema,
filters: $filters
);
}
}
11 changes: 11 additions & 0 deletions lib/Service/IDatabaseJsonService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

namespace OCA\OpenRegister\Service;

use OCP\DB\QueryBuilder\IQueryBuilder;

interface IDatabaseJsonService
{
public function filterJson(IQueryBuilder $builder, array $filters): IQueryBuilder;
public function getAggregations(IQueryBuilder $builder, array $fields, int $register, int $schema, array $filters = []): array;
}
1 change: 1 addition & 0 deletions lib/Service/MariaDBScripts/aggregations.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
(SELECT json_extract(object, '$.tooi') as gemeentecode, count(*) as count FROM nextcloud.oc_openregister_objects group by gemeentecode);
1 change: 1 addition & 0 deletions lib/Service/MariaDBScripts/filter_json.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SELECT * FROM nextcloud.oc_openregister_objects where register = 1 and json_extract(object, '$.tooi') = 0935;
54 changes: 54 additions & 0 deletions lib/Service/MySQLJsonService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

namespace OCA\OpenRegister\Service;

use OCP\DB\Exception;
use OCP\DB\QueryBuilder\IQueryBuilder;

class MySQLJsonService implements IDatabaseJsonService
{
function filterJson(IQueryBuilder $builder, array $filters): IQueryBuilder
{
unset($filters['register'], $filters['schema'], $filters['updated'], $filters['created'], $filters['_queries']);

foreach($filters as $filter=>$value) {
$builder->createNamedParameter(value: $value, placeHolder: ":value$filter");
$builder->createNamedParameter(value: "$.$filter", placeHolder: ":path$filter");

$builder
->andWhere("json_extract(object, :path$filter) = :value$filter");
}

return $builder;
}

public function getAggregations(IQueryBuilder $builder, array $fields, int $register, int $schema, array $filters = []): array
{
$facets = [];

foreach($fields as $field) {
$builder->createNamedParameter(value: "$.$field", placeHolder: ":$field");


$builder
->selectAlias($builder->createFunction("json_unquote(json_extract(object, :$field))"), '_id')
->selectAlias($builder->createFunction("count(*)"), 'count')
->from('openregister_objects')
->where(
$builder->expr()->eq('register', $builder->createNamedParameter($register, IQueryBuilder::PARAM_INT)),
$builder->expr()->eq('schema', $builder->createNamedParameter($schema, IQueryBuilder::PARAM_INT)),
)
->groupBy('_id');

$builder = $this->filterJson($builder, $filters);

$result = $builder->executeQuery();
$facets[$field] = $result->fetchAll();

$builder->resetQueryParts();
$builder->setParameters([]);

}
return $facets;
}
}
Loading