Skip to content

Commit

Permalink
Merge pull request #23 from ConductionNL/development
Browse files Browse the repository at this point in the history
Make json objects in database searchable
  • Loading branch information
rjzondervan authored Oct 18, 2024
2 parents 66f6d15 + 8c21a01 commit 163d5a0
Show file tree
Hide file tree
Showing 14 changed files with 372 additions and 53 deletions.
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

0 comments on commit 163d5a0

Please sign in to comment.