Mapeo de datos de una base de datos relacional

A veces surgen situaciones en las que la solución al problema de recuperar datos de una base de datos relacional no se ajusta a las capacidades del ORM utilizado en el proyecto, por ejemplo, ya sea por la velocidad insuficiente del ORM en sí mismo o por las consultas SQL no bastante óptimas generadas por él. En este caso, generalmente tiene que escribir consultas manualmente.

El problema es que los datos de la base de datos (incluso en respuesta a una solicitud JOIN) se devuelven como una matriz bidimensional "plana" que no refleja la compleja estructura de "árbol" de los datos de la aplicación. Es extremadamente inconveniente trabajar con una matriz de este tipo, por lo tanto, se requiere una solución más o menos universal para llevar esta matriz a una forma más adecuada de acuerdo con un patrón dado.

La solución fue encontrada, conveniente y lo suficientemente rápida.

Qué rápido


Para evaluar la velocidad de la biblioteca, armé un pequeño banco de pruebas en el que se compara la velocidad de mi biblioteca con la velocidad de Eloquent. Para las mediciones, se usó el paquete phpbench.

Para desplegar un stand en casa:

git clone https://github.com/hrustbb2/env-arrayproc-bench.git
cd env-arrayproc-bench
./env

Aquí utilicé la herramienta descrita en mi artículo anterior .

Luego en el menú seleccionamos: 1 Desarrollar, luego: 1 Construir, luego 2 Implementar y Arriba;
Luego ejecute las pruebas 5. Ejecute pruebas

Hay 3000 libros en la base de datos. Los resultados son los siguientes:

+-----------------+-----+------+------+-------------+--------------+
| subject         | set | revs | iter | mem_peak    | time_rev     |
+-----------------+-----+------+------+-------------+--------------+
| benchEloquent   | 0   | 1    | 0    | 76,442,912b | 12,781.612ms |
| benchEloquentId | 0   | 10   | 0    | 5,123,224b  | 16.432ms     |
| benchProc       | 0   | 1    | 0    | 36,364,176b | 1,053.937ms  |
| benchProcId     | 0   | 10   | 0    | 4,462,696b  | 7.684ms      |
+-----------------+-----+------+------+-------------+--------------+

benchEloquent - extrae todos los libros con los autores usando Eloquent
benchEloquentId - saca un cierto libro con los autores usando Eloquent (10 veces)

benchProc - saca todos los libros con los autores usando la biblioteca
benchProcId - saca un cierto libro con los autores usando la biblioteca (10)

para actuar las pruebas no son lo suficientemente representativas, pero la diferencia es notable, tanto en tiempo de ejecución como en consumo de memoria.

Cómo funciona


Instalar en pc:

composer require hrustbb2/arrayproc:v1.0.0

Además, por ejemplo (extremadamente simple), imagine que tenemos una base de datos de libros y autores con la siguiente estructura.

imagen

La tarea es sacar todos los libros con sus autores.

La solicitud se verá así:

SELECT
    books.id,
    books.name,
    authors.id,
    authors.name
FROM
    books
LEFT JOIN relations ON relations.books_id = books.id
LEFT JOIN authors ON authors.id = relations.authors_id

En respuesta, obtenemos tal conjunto de datos.

book.idnombre del libroauthor.idnombre del autor
1Libro 12autor2
1Libro 14 4autor4
1Libro 16 6autor6
2libro22autor2
2libro23autor3
2libro26 6autor6
2libro27 7autor7


La matriz es bidimensional, algunos campos están duplicados, por conveniencia necesita convertirlo
[
	1 => [
		'id' => 1,
		'name' => 'book1',
		'authors' => [
			2 => [
				'id' => 2,
				'name' => 'author2'
			],
			4 => [
				'id' => 4,
				'name' => 'author4'
			],
			6 => [
				'id' => 6,
				'name' => 'author6'
			],
		]
	],
	2 => [
		'id' => 2,
		'name' => 'book2',
		'authors' => [
			2 => [
				'id' => 2,
				'name' => 'author2'
			],
			3 => [
				'id' => 3,
				'name' => 'author3'
			],
			6 => [
				'id' => 6,
				'name' => 'author6'
			],
			7 => [
				'id' => 7,
				'name' => 'author7'
			],
		]
	],
]


Para hacer esto, modifique ligeramente nuestra solicitud:


SELECT
    books.id AS book_id,
    books.name AS book_name,
    authors.id AS author_id,
    authors.name AS author_name
FROM
    books
LEFT JOIN relations ON relations.books_id = books.id
LEFT JOIN authors ON authors.id = relations.authors_id

Aquí establecemos alias en la sección SELECCIONAR: para campos con datos sobre libros, alias con el prefijo 'libro_', y para campos con información sobre autores con el prefijo 'autor'.

Luego, convertimos la respuesta de la base de datos

use hrustbb2\arrayproc\ArrayProcessor;

$arrayProcessor = new ArrayProcessor();
$config = [
	'prefix' => 'book_',
	'authors' => [
		'prefix' => 'author_',
	]
]
$booksData = $arrayProcessor->process($conf, $rows)->resultArray();

donde:

$ rows es la respuesta de la base de datos en forma de una matriz de objetos / stdClass ()
$ config es una matriz asociativa que refleja la estructura de datos de la matriz resultante

Como resultado, en $ booksData tenemos una matriz en forma de árbol que tiene la estructura descrita en $ config, llena con los datos correspondientes.

Algo como esto.

All Articles