Problem/Motivation
Both Postgres and MySQL/MariaDB now support JSON fields, and adding a field backed by this field type is trivial enough, e.g. with json_field module.
However, I don't believe there's any way to query data in these fields with the entity query DBAL. This would likely require implementation of the requisite syntax in the respective database driver modules, which have been split into their own modules in Drupal 9.4.
There are definitely advantages to JSON storage of data that may currently be serialzied (e.g., #3046696: Move from serialized columns to JSON encoded data wherever possible, or use allowed_classes) but IMHO querying is the real killer feature. Data in these fields could store information similar to what you may store in a NoSQL database, but without having to employ a totally separate NoSQL backend such as MongoDB. Because Drupal's ORM is very much relational (at least for the forseeable future), being able to selectively employ JSON queries would be a huge gain.
Comments
Comment #2
bradjones1Slack conversation including good POC thoughts on this from @chx: https://drupal.slack.com/archives/C1BMUQ9U6/p1650755778329729
Comment #3
ghost of drupal pastTo summarize and better organize that discussion:
So my idea was to create field tables with identifiers and a JSON text field so like
nid,vid,langcode,uuid,field_data. Then store$.fieldname[delta].propertyin field_data. The$.fieldname[delta].propertyexpression is JSONPath notation which is what the databases use too. Entity query backends would utilize the backend overrideable mechanism, there's already apgsql.entity.query.sql,mysql.entity.query.sqlandsqlite.entity.query.sqlservices could be added. The queries themselves would use whatever JSON deconstructing functionality is made available by the database, I only tested MySQL and SQLite but I trust PostgreSQL to have similar.This requires MySQL 8.0 / MariaDB 10.6.0 and while there are tricks for earlier versions to do the querying, I believe indexing is not possible based on https://stackoverflow.com/q/35198140/308851 and that's probably enough to not want to do it. But just for completeness sake, one could utilize https://stackoverflow.com/a/51656467/308851 create the row table and write this most beautiful of queries:
Again, it's possible I am wrong but StackOverflow is usually reliable enough, even in negatives. As a side note, even bona fide document databases used to struggle with indexing arrays https://jira.mongodb.org/browse/SERVER-826
SQLite, same table:
Based on https://news.ycombinator.com/item?id=13556517 these were present in JSON1. Indexing is left as an exercise to the reader :) but https://dgl.cx/2020/06/sqlite-json-support looks very relevant. 3.31.0 might be needed.
Overall, due to the version requirements and the amount of work required, I suspect this might be a Drupal 11 feature.
Finally, a note on languages: yes, this would require storing non-translatable values multiple times, once for each translation but I believe moving the language into the field data would get even messier. But these are just my starting thoughts and if this is indeed Drupal 11 then there's plenty of time for research and experimentation. I do not intend to take this issue any further than this.
Comment #4
bradjones1That's a great summary.
In the meantime, any thoughts from the collective on supporting JSON-backed, queryable field data on what would basically be an opt-in basis per field? E.g., the data type from json_field module (which is very simple) and the querying logic added to the DB backends, as proposed above? That might 1) get into core faster, since it's not changing anything about Field API vis-a-vis storage schemas and 2) help encourage use cases/exploration of this by site owners without requiring core to change "first"?
I started exploring this issue in my case to provide some ability to query data which is otherwise stored in a
mapdata type...which right now is just serialized. I haven't seen map used in the wild a ton, but e.g. Commerce has adatafield on some entity types which could be a real gold mine for this kind of querying.Comment #5
catchAdding a JSON alternative to
mapvs. converting the entity storage itself to JSON are two very different things. I think it's best handled in two almost completely independent issues. That's definitely a smaller change that could probably be done much easier.For entity storage, this is very interesting, however the massive barriers will be the upgrade path and backwards compatibility for things like views data. It might need to be a new module, that starts out experimental, and might even need to stay opt-in after becoming stable so that sites can migrate on their own schedule. Then if it's successful we could eventually move the old entity sql storage classes to contrib and deprecate in core or something like that.
Comment #6
bradjones1Re: #5 - Agree 100%. What is common between these two related proposals would, I think, be the added support for JSON path queries in the entity query drivers. Which would be a great POC for basically making all field data storage as some derivative of this json field type.
I forked off #3277081: [Plan] Convert field storage to use JSON fields to represent the "converting the entity storage itself" path. Feel free to re-categorize if I selected the wrong component. I feel like this issue still pretty well sums up the "let me query this data, where it exists" path.
Comment #8
andypostIt missing issue for sqlite and display at status page
Comment #10
bradjones1Added #3325871: Support JSON fields in SQLite for SQLite implementation.
Comment #11
anybodyComment #12
geek-merlinI'm all with catch (#5) in that this needs workable steps. Started to code a json_map_field (will share soon, collaborators welcome), but realized that this is currently impossible, as serialization of the builtin map field relies on a megadeth kittenkiller hack.
Started some work in the related (9y old!) issue.
Comment #14
effulgentsia commentedThe title of this issue says "entity queries", but to support this in entity queries we must first support this in Drupal's database API itself. I opened #3378275: Add support for JSON field queries in database API as a child issue of this meta for discussing and implementing that step.
Comment #15
catchComment #16
bradjones1I'm going to close this as a duplicate since due to all the tight coupling with the database API changes over in #3343634: Add "json" as core data type to Schema and Database API.