mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-10-05 14:28:08 +03:00
RFC: NoSQL Schema Sampling RFC
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/9603 GitOrigin-RevId: b7029b9ddf38086cc05002631c844eff91efd70f
This commit is contained in:
parent
a394510252
commit
f6ac976bda
42
rfcs/nosql-schema-sampling/docker-compose.yml
Normal file
42
rfcs/nosql-schema-sampling/docker-compose.yml
Normal file
@ -0,0 +1,42 @@
|
||||
version: '3'
|
||||
services:
|
||||
|
||||
# External MongoDB sample database
|
||||
mongodb:
|
||||
image: mongo:6
|
||||
container_name: mongodb_mongo
|
||||
ports:
|
||||
- 27017:27017
|
||||
volumes:
|
||||
# Imports sample database:
|
||||
- ./sample_data/import.sh:/docker-entrypoint-initdb.d/import.sh
|
||||
- ./sample_data/sample_mflix:/sample_data/sample_mflix
|
||||
environment:
|
||||
MONGO_INITDB_ROOT_USERNAME: root
|
||||
MONGO_INITDB_ROOT_PASSWORD: password
|
||||
healthcheck:
|
||||
test: echo 'db.runCommand("ping").ok' | mongosh localhost:27017/test --quiet
|
||||
interval: 5s
|
||||
timeout: 10s
|
||||
retries: 5
|
||||
start_period: 10s
|
||||
|
||||
# External service which will be used for sampling
|
||||
mongodb_sampler:
|
||||
image: node
|
||||
container_name: mongodb_sampling
|
||||
environment:
|
||||
MONGO_DATABASE: mongodb://root:password@mongodb:27017/sample_mflix
|
||||
MONGO_USERNAME: root
|
||||
MONGO_PASSWORD: password
|
||||
MONGO_SELECT_COLLECTIONS: '' # which collections to analyze and sample. ('' [all collections]), (movies,comments)
|
||||
MONGO_UPDATE_COLLECTIONS: true # automatically update collections in database with validation schemas. (true or false [or blank])
|
||||
volumes:
|
||||
# Scripts to analuze the database and create the validation schema:
|
||||
- ./schema_sampler:/schema_sampler
|
||||
# Final results will be stored here:
|
||||
- ./schema_exports:/schema_exports
|
||||
command: bash -c "/schema_sampler/analyze.sh"
|
||||
depends_on:
|
||||
mongodb:
|
||||
condition: service_healthy
|
81
rfcs/nosql-schema-sampling/readme.md
Normal file
81
rfcs/nosql-schema-sampling/readme.md
Normal file
@ -0,0 +1,81 @@
|
||||
# RFC: NoSQL sampling for automatic schema generation
|
||||
|
||||
As we operate in an environment encompassing both SQL and NoSQL databases, the inherent unstructured nature of NoSQL presents specific challenges.
|
||||
|
||||
Despite the flexibility and scalability advantages of NoSQL databases, managing data efficiently becomes a complex task, particularly in the context of ensuring a predictable API and improved coding ergonomics.
|
||||
|
||||
|
||||
## Problems / description
|
||||
- **Inherent unstructured nature of NoSQL**: NoSQL databases, such as MongoDB, lack a predefined schema. This feature, while enabling flexibility, complicates the definition and management of data.
|
||||
- **GraphQL provides guardrails, but requires structure**: GraphQL introduces un-opinionated guardrails around the NoSQL data source. Our approach provides type safety, enhances execution performance, enables predictable APIs, and improves coding ergonomics.
|
||||
- **Ease and speed of onboarding**: The current state renders onboarding with GraphQL and NoSQL databases a complex process. The absence of a predefined schema in NoSQL databases makes it harder for newcomers to "plug-in" their data sources the same way they would with SQL databases.
|
||||
- **Limited used of validation schema**: One of our current solutions is to use the validation schema in MongoDB. However, this solution is not widely used by our users.
|
||||
- **Feature parity**: Providing users with capabilities to instantly introspect and track their Collections and Documents across MongoDB databases can expedite their onboarding process with Hasura and elevate NoSQL databases to feature parity with other schema-based databases supported by Hasura.
|
||||
|
||||
## Proposed solution
|
||||
To address these challenges, the proposal is for an automatic schema generation tool leveraging NoSQL sampling techniques is proposed.
|
||||
|
||||
A proof-of-concept is below for MongoDB, and the same approach can be applied to other NoSQL databases.
|
||||
|
||||
Essentially, the idea around is that we can use sampling to take either the entire, or a subset of a collection's documents.
|
||||
Then we would run an analysis to get an idea about the shapes and types that are found within the universe of documents in the schema. Then we would use that analysis to generate a schema which could be used as an onboarding starting point to power the GraphQL schema in Hasura.
|
||||
|
||||
This schema would then be customizable to allow for changes as needed by the end-user.
|
||||
|
||||
## Open questions
|
||||
- What kind of selectors are necessary to be able to select the right documents?
|
||||
- For example in MongoDB, we have the ability to select documents based on a query, maxed depth, based on a percentage of the collection, or based on a max number of records.
|
||||
- How should the tooling select which type to use when there are conflicting types?
|
||||
- For example, if a certain field has majority `int` types and a couple of `string` types, which should be taken?
|
||||
- Would this need to be configurable?
|
||||
- When authoring the schema, should we have the option
|
||||
- For example, certain situations where very few optional embedded-objects which are contained only in a few records in a collection.
|
||||
- Should we have something like a 'must have been found in x % of documents' setting?
|
||||
- Should this be implemented into core tools, or is there a flexibility in being able to have this as part of an external set of tools?
|
||||
- How can this be implemented in a way which is reproducible for other NoSQL database vendors.
|
||||
|
||||
-----
|
||||
|
||||
## Proof-of-concept
|
||||
|
||||
We've created a proof of concept for a schema sampler that can be run against a MongoDB database.
|
||||
|
||||
It's built using a combination of **mongosh** (https://www.mongodb.com/docs/mongodb-shell/), **Variety** MongoDB schema analyzer (https://github.com/variety/variety), and Node.js.
|
||||
|
||||
It generates a MongoDB validation schema based on the analysis of the documents in the collection, and then optionally will apply it to the database.
|
||||
|
||||
*[Later this same work can be used for generating Hasura-representations of the schema using our logical models as well.]*
|
||||
|
||||
That schema can then be used by Hasura to generate a GraphQL schema on top of the MongoDB datasource.
|
||||
|
||||
### How do I get started
|
||||
- `docker compose up`
|
||||
- Runs MongoDB and loads up the `sample_mflix` sample database.
|
||||
- Has a healthcheck so the sampler shouldn't run till the database is ready.
|
||||
- Sampler runs `/schema_sampler/archive.sh` which bootstraps introspecting the collections, running them through variety, converting the analysis to a validation schema, and then updating that schema back into MongoDB.
|
||||
|
||||
### How can I customize what is being introspected and sampled?
|
||||
The docker container currently contains some environment variables below which can be used for selecting the collections to analyze and sample.
|
||||
|
||||
If you'd like to customize the sampling method, you can edit the `./schema_sampler/analyze.sh` file.
|
||||
|
||||
On line 29 there's:
|
||||
```bash
|
||||
mongosh ${MONGO_DATABASE} --quiet --eval "var collection = '${collection//\'/}', outputFormat='json'" --username ${MONGO_USERNAME} --password ${MONGO_PASSWORD} --authenticationDatabase=admin /schema_sampler/variety.js > "/schema_exports/analysis/${collection//\'/}.json"
|
||||
```
|
||||
which is where the data is retrieved for sampling using `mongosh`. You can edit the `--eval` command to change the sampling method (for example, adding a `find()` to only records using version of a schema, or a `limit()` to only return the first 5000 records).
|
||||
|
||||
|
||||
### Want to know more about what's happening
|
||||
Running `docker logs mongodb_sampling` would allow you to see what was run when inside the sampling container.
|
||||
|
||||
### ./schema_exports volume mount
|
||||
Will contain the intermediate analysis files and JSON files for the validation schema export.
|
||||
|
||||
### Docker environment variables
|
||||
The `mongodb_sampler` container has a few environment variable helpers which you can set:
|
||||
- `MONGO_DATABASE`: The MongoDB connection string.
|
||||
- `MONGO_USERNAME`: The MongoDB username.
|
||||
- `MONGO_PASSWORD`: The MongoDB password.
|
||||
- `MONGO_SELECT_COLLECTIONS`: Which collections to analyze and sample. ('' [for all collections]), (movies,comments)
|
||||
- `MONGO_UPDATE_COLLECTIONS`: Automatically update collections in the database with the generated validation schemas. (true or false [or blank for false])
|
10
rfcs/nosql-schema-sampling/sample_data/import.sh
Executable file
10
rfcs/nosql-schema-sampling/sample_data/import.sh
Executable file
@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
|
||||
# MFlix Dummy Data
|
||||
echo "📡 Importing mflix sample data..."
|
||||
mongoimport --host localhost:27017 --username root --password password --authenticationDatabase=admin --db sample_mflix --collection comments --file /sample_data/sample_mflix/comments.json
|
||||
mongoimport --host localhost:27017 --username root --password password --authenticationDatabase=admin --db sample_mflix --collection movies --file /sample_data/sample_mflix/movies.json
|
||||
mongoimport --host localhost:27017 --username root --password password --authenticationDatabase=admin --db sample_mflix --collection sessions --file /sample_data/sample_mflix/sessions.json
|
||||
mongoimport --host localhost:27017 --username root --password password --authenticationDatabase=admin --db sample_mflix --collection theaters --file /sample_data/sample_mflix/theaters.json
|
||||
mongoimport --host localhost:27017 --username root --password password --authenticationDatabase=admin --db sample_mflix --collection users --file /sample_data/sample_mflix/users.json
|
||||
echo "✅ Mflix sample data imported..."
|
50304
rfcs/nosql-schema-sampling/sample_data/sample_mflix/comments.json
Normal file
50304
rfcs/nosql-schema-sampling/sample_data/sample_mflix/comments.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,186 @@
|
||||
email,points_total,points_wallet,tier
|
||||
aidan_gillen@gameofthron.es,371118,92780,Gold
|
||||
harry_lloyd@gameofthron.es,243542,81181,Silver
|
||||
michelle_fairley@gameofthron.es,301074,301074,Silver
|
||||
kit_harington@gameofthron.es,840961,210240,Silver
|
||||
sophie_turner@gameofthron.es,896887,298962,Silver
|
||||
maisie_williams@gameofthron.es,232576,116288,Silver
|
||||
richard_madden@gameofthron.es,888334,888334,Silver
|
||||
alfie_allen@gameofthron.es,328439,65688,Gold
|
||||
isaac_hempstead_wright@gameofthron.es,55755,11151,Silver
|
||||
mark_addy@gameofthron.es,760455,380228,Silver
|
||||
rory_mccann@gameofthron.es,921802,921802,Silver
|
||||
sean_bean@gameofthron.es,121698,121698,Silver
|
||||
jack_gleeson@gameofthron.es,522857,174286,Silver
|
||||
nikolaj_coster-waldau@gameofthron.es,311769,311769,Silver
|
||||
iain_glen@gameofthron.es,892838,446419,Silver
|
||||
jason_momoa@gameofthron.es,886541,295514,Silver
|
||||
lena_headey@gameofthron.es,376561,125520,Silver
|
||||
peter_dinklage@gameofthron.es,604113,302057,Silver
|
||||
jerome_flynn@gameofthron.es,130830,43610,Silver
|
||||
emilia_clarke@gameofthron.es,212897,212897,Silver
|
||||
conleth_hill@gameofthron.es,382143,382143,Silver
|
||||
sibel_kekilli@gameofthron.es,183257,36651,Silver
|
||||
charles_dance@gameofthron.es,237769,59442,Silver
|
||||
james_cosmo@gameofthron.es,483039,483039,Silver
|
||||
rose_leslie@gameofthron.es,268091,268091,Silver
|
||||
joe_dempsie@gameofthron.es,756231,252077,Silver
|
||||
kristofer_hivju@gameofthron.es,218877,43775,Silver
|
||||
oona_chaplin@gameofthron.es,981827,327276,Silver
|
||||
natalie_dormer@gameofthron.es,101141,33714,Silver
|
||||
hannah_murray@gameofthron.es,278877,278877,Silver
|
||||
gwendoline_christie@gameofthron.es,47643,11911,Silver
|
||||
iwan_rheon@gameofthron.es,10021,5011,Silver
|
||||
michiel_huisman@gameofthron.es,748972,149794,Silver
|
||||
indira_varma@gameofthron.es,453672,113418,Silver
|
||||
liam_cunningham@gameofthron.es,7458,3729,Silver
|
||||
john_bradley-west@gameofthron.es,268615,67154,Silver
|
||||
nathalie_emmanuel@gameofthron.es,581997,145499,Silver
|
||||
stephen_dillane@gameofthron.es,963996,963996,Silver
|
||||
dean-charles_chapman@gameofthron.es,428911,214456,Silver
|
||||
jonathan_pryce@gameofthron.es,315519,105173,Silver
|
||||
natalia_tena@gameofthron.es,368297,92074,Silver
|
||||
carice_van_houten@gameofthron.es,829341,207335,Silver
|
||||
mark_stanley@gameofthron.es,37041,7408,Silver
|
||||
art_parkinson@gameofthron.es,784606,392303,Silver
|
||||
esme_bianco@gameofthron.es,447069,223535,Silver
|
||||
hafthór_júlíus_björnsson@gameofthron.es,498905,124726,Silver
|
||||
dominic_carter@gameofthron.es,734054,734054,Silver
|
||||
kristian_nairn@gameofthron.es,979762,244941,Silver
|
||||
nell_tiger_free@gameofthron.es,554970,138743,Silver
|
||||
donald_sumpter@gameofthron.es,306128,61226,Silver
|
||||
ron_donachie@gameofthron.es,691770,230590,Silver
|
||||
eugene_simon@gameofthron.es,903412,903412,Silver
|
||||
amrita_acharia@gameofthron.es,331518,110506,Silver
|
||||
ian_mcelhinney@gameofthron.es,428641,428641,Silver
|
||||
ian_gelder@gameofthron.es,880463,220116,Silver
|
||||
roxanne_mckee@gameofthron.es,913367,913367,Silver
|
||||
tom_wlaschiha@gameofthron.es,806067,161213,Silver
|
||||
michael_mcelhatton@gameofthron.es,712946,237649,Silver
|
||||
julian_glover@gameofthron.es,729666,364833,Silver
|
||||
ian_beattie@gameofthron.es,829971,414986,Silver
|
||||
finn_jones@gameofthron.es,41975,8395,Silver
|
||||
ben_hawkey@gameofthron.es,919040,229760,Silver
|
||||
richard_dormer@gameofthron.es,760838,380419,Silver
|
||||
brian_fortune@gameofthron.es,227457,75819,Silver
|
||||
daniel_portman@gameofthron.es,860359,286786,Silver
|
||||
gemma_whelan@gameofthron.es,576875,144219,Silver
|
||||
ben_crompton@gameofthron.es,138273,46091,Silver
|
||||
tara_fitzgerald@gameofthron.es,715873,143175,Silver
|
||||
jacob_anderson@gameofthron.es,310174,310174,Silver
|
||||
anton_lesser@gameofthron.es,742440,247480,Silver
|
||||
diana_rigg@gameofthron.es,371490,185745,Silver
|
||||
kerry_ingram@gameofthron.es,391027,97757,Silver
|
||||
ellie_kendrick@gameofthron.es,78367,15673,Silver
|
||||
peter_vaughan@gameofthron.es,604767,604767,Silver
|
||||
josef_altin@gameofthron.es,243760,121880,Silver
|
||||
owen_teale@gameofthron.es,88378,17676,Silver
|
||||
thomas_brodie-sangster@gameofthron.es,532844,266422,Silver
|
||||
greg_powell@fakegmail.com,407562,407562,Silver
|
||||
sarah_lewis@fakegmail.com,824644,164929,Silver
|
||||
luke_barnes@gameofthron.es,160328,160328,Silver
|
||||
emily_ellis@fakegmail.com,469838,117460,Silver
|
||||
victor_patel@fakegmail.com,867965,867965,Silver
|
||||
karina_martin@fakegmail.com,112758,28190,Silver
|
||||
robert_jordan@fakegmail.com,128847,42949,Silver
|
||||
roger_ashton-griffiths@gameofthron.es,271252,135626,Silver
|
||||
ronald_cox@fakegmail.com,311671,311671,Silver
|
||||
paul_kaye@gameofthron.es,454847,227424,Silver
|
||||
faye_marsay@gameofthron.es,22891,4578,Silver
|
||||
brenock_o'connor@gameofthron.es,801111,801111,Silver
|
||||
michael_condron@gameofthron.es,439425,109856,Silver
|
||||
richard_davis@fakegmail.com,915945,915945,Silver
|
||||
lisa_rasmussen@fakegmail.com,34923,11641,Silver
|
||||
cameron_duran@fakegmail.com,857339,171468,Silver
|
||||
connie_johnson@fakegmail.com,370285,123428,Silver
|
||||
victor_fleming@fakegmail.com,54277,13569,Silver
|
||||
brandon_hardy@fakegmail.com,97445,24361,Silver
|
||||
kathryn_sosa@fakegmail.com,754069,251356,Silver
|
||||
mrs._ariana_nunez@fakegmail.com,623715,311858,Silver
|
||||
megan_richards@fakegmail.com,964334,192867,Silver
|
||||
yvette_roth@fakegmail.com,270710,90237,Silver
|
||||
kelsey_smith@fakegmail.com,249892,249892,Silver
|
||||
keith_phillips@fakegmail.com,395806,131935,Silver
|
||||
morgan_smith@fakegmail.com,66282,66282,Silver
|
||||
jason_smith@fakegmail.com,934336,186867,Silver
|
||||
megan_turner@fakegmail.com,500910,125228,Silver
|
||||
amy_phillips@fakegmail.com,787274,787274,Silver
|
||||
garrett_obrien@fakegmail.com,38211,38211,Silver
|
||||
lori_franklin@fakegmail.com,989731,329910,Silver
|
||||
daniel_simmons@fakegmail.com,208109,104055,Silver
|
||||
kenneth_chandler@fakegmail.com,48025,48025,Silver
|
||||
paula_sullivan@fakegmail.com,872563,290854,Silver
|
||||
brenda_martin@fakegmail.com,724785,241595,Silver
|
||||
javier_smith@fakegmail.com,951895,317298,Silver
|
||||
anthony_thompson@fakegmail.com,189915,47479,Silver
|
||||
joshua_kent@fakegmail.com,882747,882747,Silver
|
||||
thomas_buckley@fakegmail.com,420065,140022,Silver
|
||||
richard_schmidt@fakegmail.com,53736,13434,Silver
|
||||
anthony_smith@fakegmail.com,894242,298081,Silver
|
||||
michael_day@fakegmail.com,454053,90811,Silver
|
||||
mercedes_tyler@fakegmail.com,250400,250400,Silver
|
||||
kristen_schmidt@fakegmail.com,848357,169671,Silver
|
||||
john_roman@fakegmail.com,787724,157545,Silver
|
||||
justin_williams@fakegmail.com,218323,43665,Silver
|
||||
april_cole@fakegmail.com,836859,167372,Silver
|
||||
kimberly_gates@fakegmail.com,402820,201410,Silver
|
||||
andrea_le@fakegmail.com,609108,609108,Silver
|
||||
patricia_good@fakegmail.com,122754,30689,Silver
|
||||
barbara_gonzalez@fakegmail.com,44221,8844,Silver
|
||||
denise_bryant@fakegmail.com,871607,217902,Silver
|
||||
victoria_sanders@fakegmail.com,664957,166239,Silver
|
||||
taylor_scott@fakegmail.com,644595,128919,Silver
|
||||
taylor_hill@fakegmail.com,405497,202749,Silver
|
||||
melissa_jones@fakegmail.com,11417,2854,Silver
|
||||
amy_ramirez@fakegmail.com,125842,41947,Silver
|
||||
christopher_robinson@fakegmail.com,32960,8240,Silver
|
||||
phillip_collins@fakegmail.com,603906,120781,Silver
|
||||
edward_barrett@fakegmail.com,602701,602701,Silver
|
||||
lisa_russo@fakegmail.com,937347,234337,Silver
|
||||
thomas_morris@fakegmail.com,261675,65419,Silver
|
||||
ms._cathy_miller@fakegmail.com,823506,274502,Silver
|
||||
elizabeth_wiggins@fakegmail.com,299691,59938,Silver
|
||||
lisa_silva@fakegmail.com,585507,117101,Silver
|
||||
nicholas_webster@fakegmail.com,328813,82203,Silver
|
||||
teresa_thomas@fakegmail.com,555871,185290,Silver
|
||||
catherine_romero@fakegmail.com,521251,173750,Silver
|
||||
michael_moore@fakegmail.com,264405,132203,Silver
|
||||
christian_williams@fakegmail.com,717067,239022,Silver
|
||||
jason_hernandez@fakegmail.com,236401,118201,Silver
|
||||
denise_davidson@fakegmail.com,917670,917670,Silver
|
||||
julia_nichols@fakegmail.com,564357,282179,Silver
|
||||
heather_leonard@fakegmail.com,417756,208878,Silver
|
||||
melissa_young@fakegmail.com,382306,191153,Silver
|
||||
john_rice@fakegmail.com,92771,46386,Silver
|
||||
blake_sellers@fakegmail.com,98598,49299,Silver
|
||||
theresa_holmes@fakegmail.com,953901,476951,Silver
|
||||
bradley_brooks@fakegmail.com,862238,431119,Silver
|
||||
thomas_green@fakegmail.com,945350,945350,Silver
|
||||
jonathon_mccullough@fakegmail.com,632841,126568,Silver
|
||||
jerry_cabrera@fakegmail.com,998842,332947,Silver
|
||||
jamie_santana@fakegmail.com,15383,3077,Silver
|
||||
mary_mitchell@fakegmail.com,757125,252375,Silver
|
||||
lori_blankenship@fakegmail.com,393159,98290,Silver
|
||||
deborah_kennedy@fakegmail.com,708578,141716,Silver
|
||||
paul_bailey@fakegmail.com,81747,27249,Silver
|
||||
john_bishop@fakegmail.com,87902,87902,Silver
|
||||
yolanda_owen@fakegmail.com,209542,52386,Silver
|
||||
nichole_miller@fakegmail.com,61299,61299,Silver
|
||||
nicholas_johnson@fakegmail.com,708229,236076,Silver
|
||||
desiree_pierce@fakegmail.com,447206,111802,Silver
|
||||
connie_barton@fakegmail.com,934306,311435,Silver
|
||||
anthony_cline@fakegmail.com,421413,84283,Silver
|
||||
donna_russell@fakegmail.com,852408,426204,Silver
|
||||
blake_fitzgerald@fakegmail.com,115132,38377,Silver
|
||||
shawn_mccormick@fakegmail.com,225350,112675,Silver
|
||||
anthony_hurst@fakegmail.com,664729,664729,Silver
|
||||
patrick_knight@fakegmail.com,287900,143950,Silver
|
||||
ashlee_hart@fakegmail.com,137174,27435,Silver
|
||||
magicz@cats.com,54179,54179,Silver
|
||||
foobaz@bar.com,147268,147268,Silver
|
||||
eric_navarro@fakegmail.com,958557,191711,Silver
|
||||
donna_smith@fakegmail.com,245313,81771,Silver
|
||||
jose_hall@fakegmail.com,878644,292881,Silver
|
||||
jeffrey_roberts@fakegmail.com,496826,124207,Silver
|
||||
jordan_medina@fakegmail.com,695384,347692,Silver
|
||||
jennifer_frazier@fakegmail.com,335727,111909,Silver
|
|
23539
rfcs/nosql-schema-sampling/sample_data/sample_mflix/movies.json
Normal file
23539
rfcs/nosql-schema-sampling/sample_data/sample_mflix/movies.json
Normal file
File diff suppressed because one or more lines are too long
@ -0,0 +1 @@
|
||||
{"_id":{"$oid":"5a97f9c91c807bb9c6eb5fb4"},"user_id":"t3qulfeem@kwiv5.6ur","jwt":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1MTk5MDkzMjEsIm5iZiI6MTUxOTkwOTMyMSwianRpIjoiNmJlZDAwMWYtNTFiYi00NzVhLTgxZDAtMDcwNGE5Mjk0MWZlIiwiZXhwIjoxNTE5OTEwMjIxLCJpZGVudGl0eSI6eyJlbWFpbCI6InQzcXVsZmVlbUBrd2l2NS42dXIiLCJuYW1lIjoiM2lveHJtZnF4IiwicGFzc3dvcmQiOm51bGx9LCJmcmVzaCI6ZmFsc2UsInR5cGUiOiJhY2Nlc3MiLCJ1c2VyX2NsYWltcyI6eyJ1c2VyIjp7ImVtYWlsIjoidDNxdWxmZWVtQGt3aXY1LjZ1ciIsIm5hbWUiOiIzaW94cm1mcXgiLCJwYXNzd29yZCI6bnVsbH19fQ.ejtr_NyZyBronWMKuE0RFTjWej--T0zGrdc_iymGtVs"}
|
1564
rfcs/nosql-schema-sampling/sample_data/sample_mflix/theaters.json
Normal file
1564
rfcs/nosql-schema-sampling/sample_data/sample_mflix/theaters.json
Normal file
File diff suppressed because it is too large
Load Diff
185
rfcs/nosql-schema-sampling/sample_data/sample_mflix/users.json
Normal file
185
rfcs/nosql-schema-sampling/sample_data/sample_mflix/users.json
Normal file
@ -0,0 +1,185 @@
|
||||
{"_id":{"$oid":"59b99db4cfa9a34dcd7885b6"},"name":"Ned Stark","email":"sean_bean@gameofthron.es","password":"$2b$12$UREFwsRUoyF0CRqGNK0LzO0HM/jLhgUCNNIJ9RJAqMUQ74crlJ1Vu"}
|
||||
{"_id":{"$oid":"59b99db4cfa9a34dcd7885b7"},"name":"Robert Baratheon","email":"mark_addy@gameofthron.es","password":"$2b$12$yGqxLG9LZpXA2xVDhuPnSOZd.VURVkz7wgOLY3pnO0s7u2S1ZO32y"}
|
||||
{"_id":{"$oid":"59b99db5cfa9a34dcd7885b8"},"name":"Jaime Lannister","email":"nikolaj_coster-waldau@gameofthron.es","password":"$2b$12$6vz7wiwO.EI5Rilvq1zUc./9480gb1uPtXcahDxIadgyC3PS8XCUK"}
|
||||
{"_id":{"$oid":"59b99db5cfa9a34dcd7885b9"},"name":"Catelyn Stark","email":"michelle_fairley@gameofthron.es","password":"$2b$12$fiaTH5Sh1zKNFX2i/FTEreWGjxoJxvmV7XL.qlfqCr8CwOxK.mZWS"}
|
||||
{"_id":{"$oid":"59b99db6cfa9a34dcd7885ba"},"name":"Cersei Lannister","email":"lena_headey@gameofthron.es","password":"$2b$12$FExjgr7CLhNCa.oUsB9seub8mqcHzkJCFZ8heMc8CeIKOZfeTKP8m"}
|
||||
{"_id":{"$oid":"59b99db6cfa9a34dcd7885bb"},"name":"Daenerys Targaryen","email":"emilia_clarke@gameofthron.es","password":"$2b$12$NzpbWHdMytemLtTfFKduHenr2NZ.rvxIKuYM4AWLTFaUShxbJ.G3q"}
|
||||
{"_id":{"$oid":"59b99db6cfa9a34dcd7885bc"},"name":"Jorah Mormont","email":"iain_glen@gameofthron.es","password":"$2b$12$K8bKkwnpkrjsBPzASZxO/.yj7d9kvupiVtO6JA3Xl106AKXr3pXFK"}
|
||||
{"_id":{"$oid":"59b99db7cfa9a34dcd7885bd"},"name":"Petyr Baelish","email":"aidan_gillen@gameofthron.es","password":"$2b$12$qM.YvmiekyYYY7p7phpK3OicbRCDkN7ESwYAnG/o9YnfHC0Mhkmbi"}
|
||||
{"_id":{"$oid":"59b99db8cfa9a34dcd7885be"},"name":"Viserys Targaryen","email":"harry_lloyd@gameofthron.es","password":"$2b$12$cpwVmU4DyuQxgwpdrVJhaudzbKOXlHRbf.tpCuHjpAqonuoyvvEG6"}
|
||||
{"_id":{"$oid":"59b99db9cfa9a34dcd7885bf"},"name":"Jon Snow","email":"kit_harington@gameofthron.es","password":"$2b$12$fDEu1Ru66tLWAVidMN.b0.929BlfnyqdGuhWMyzfOAf/ATYOyLoY6"}
|
||||
{"_id":{"$oid":"59b99db9cfa9a34dcd7885c0"},"name":"Sansa Stark","email":"sophie_turner@gameofthron.es","password":"$2b$12$nCIVE81..AtAoysPZkl19.G5V0EdIwwsZh1f18lxWEr3dlpG/Uusi"}
|
||||
{"_id":{"$oid":"59b99dbacfa9a34dcd7885c1"},"name":"Arya Stark","email":"maisie_williams@gameofthron.es","password":"$2b$12$19h3KjeTg3/sPNFHztdb6eGWKrCxIwlVXVSh9POSi5PS9kSlguZEq"}
|
||||
{"_id":{"$oid":"59b99dbacfa9a34dcd7885c2"},"name":"Robb Stark","email":"richard_madden@gameofthron.es","password":"$2b$12$XPLvWQW7tjWc/PX9jMVRnO8w.lR6hv144ee8pc8nDsWIAWxfwxHzy"}
|
||||
{"_id":{"$oid":"59b99dbbcfa9a34dcd7885c3"},"name":"Theon Greyjoy","email":"alfie_allen@gameofthron.es","password":"$2b$12$x574mziridS3mEQVTbKbY.lK.ngIDyZJnTw17G7Gk6n4lnWVSrWL."}
|
||||
{"_id":{"$oid":"59b99dbbcfa9a34dcd7885c4"},"name":"Bran Stark","email":"isaac_hempstead_wright@gameofthron.es","password":"$2b$12$Z7/ztVm8eWMDwTg.doS.UO7JbsbA9IbLomND1VxIZEdAN3keW6csS"}
|
||||
{"_id":{"$oid":"59b99dbbcfa9a34dcd7885c5"},"name":"Joffrey Baratheon","email":"jack_gleeson@gameofthron.es","password":"$2b$12$fIYLjRg5tZcTcqy30.MJLO4JRblLhsIhFwYTgUpFBbvnf9S4ONbtW"}
|
||||
{"_id":{"$oid":"59b99dbccfa9a34dcd7885c6"},"name":"Sandor Clegane","email":"rory_mccann@gameofthron.es","password":"$2b$12$DKIKOBMbN76vskkRyJ1AjuELigfnx.SeG8vu73k24kfMcO637bSqa"}
|
||||
{"_id":{"$oid":"59b99dbdcfa9a34dcd7885c7"},"name":"Tyrion Lannister","email":"peter_dinklage@gameofthron.es","password":"$2b$12$xtHwQNXYlQzP2REobUDlzuQimjzBlXrTx1GnwP.xkfULeuuUpRxa2"}
|
||||
{"_id":{"$oid":"59b99dbdcfa9a34dcd7885c8"},"name":"Khal Drogo","email":"jason_momoa@gameofthron.es","password":"$2b$12$7tgpVkBxUqQiYFkHjZyoMuEzFU5BSI.FYkOXHu4zCRlRsa15sHQo6"}
|
||||
{"_id":{"$oid":"59b99dbecfa9a34dcd7885c9"},"name":"Davos Seaworth","email":"liam_cunningham@gameofthron.es","password":"$2b$12$jbgNoWG97LHNIm4axwXDz.tkFITsmw/aylIY/lZDaJRgnHZjB029e"}
|
||||
{"_id":{"$oid":"59b99dbecfa9a34dcd7885ca"},"name":"Samwell Tarly","email":"john_bradley-west@gameofthron.es","password":"$2b$12$ZcZj9wKjlT/dCCrmupiZZ..JA3c9HoufxRygL1DkY9hsClT0iyflG"}
|
||||
{"_id":{"$oid":"59b99dbecfa9a34dcd7885cb"},"name":"Margaery Tyrell","email":"natalie_dormer@gameofthron.es","password":"$2b$12$AjC.876rd2dgsSIu.5c4qembdVfdDajMIgueMYuOBoskJUGHzpw46"}
|
||||
{"_id":{"$oid":"59b99dbfcfa9a34dcd7885cc"},"name":"Stannis Baratheon","email":"stephen_dillane@gameofthron.es","password":"$2b$12$vbPwOM9QkSOsOXRgLSZiqe9JPJtBX1JUwm06d3lYVViKxrYCIyhEm"}
|
||||
{"_id":{"$oid":"59b99dbfcfa9a34dcd7885cd"},"name":"Melisandre","email":"carice_van_houten@gameofthron.es","password":"$2b$12$ZdSvCDMwVLFgJGDOsDbFLOD/utICnkbJV0OVJJ8lUHqSK3VbuqKuS"}
|
||||
{"_id":{"$oid":"59b99dbfcfa9a34dcd7885ce"},"name":"Jeor Mormont","email":"james_cosmo@gameofthron.es","password":"$2b$12$tz5dSvAjtduFuuXFQwMH2OJwb3QKr9/gR5uefaQ3gHJojhLaKxdNK"}
|
||||
{"_id":{"$oid":"59b99dc0cfa9a34dcd7885cf"},"name":"Bronn","email":"jerome_flynn@gameofthron.es","password":"$2b$12$9rzMIF3lv7kASdTdam2eOOjWrDSN.qi2hpY5tyOfDPe545XfrQHpu"}
|
||||
{"_id":{"$oid":"59b99dc0cfa9a34dcd7885d0"},"name":"Varys","email":"conleth_hill@gameofthron.es","password":"$2b$12$mV9NHXHLISu3fDdd6jtU2.6DstBgnC6iWQQR.1h/MsDZp3ftTUBSq"}
|
||||
{"_id":{"$oid":"59b99dc0cfa9a34dcd7885d1"},"name":"Shae","email":"sibel_kekilli@gameofthron.es","password":"$2b$12$FyKikoJynO1kGJ6cTuXaKeKRWauwI5TNlTYiNBgPnizN6XoGB8qpi"}
|
||||
{"_id":{"$oid":"59b99dc2cfa9a34dcd7885d2"},"name":"Tywin Lannister","email":"charles_dance@gameofthron.es","password":"$2b$12$/i04T5yEJvmsBhF0Jd.kJOk3ZhRzezbTU7ASEM5o43Xxsa4o6IgEy"}
|
||||
{"_id":{"$oid":"59b99dc2cfa9a34dcd7885d3"},"name":"Ygritte","email":"rose_leslie@gameofthron.es","password":"$2b$12$knwl2v71.oOhFA1W.Yenle8kil56LqhWCOvM7/JVy8E5YrOoZisUi"}
|
||||
{"_id":{"$oid":"59b99dc2cfa9a34dcd7885d4"},"name":"Talisa Maegyr","email":"oona_chaplin@gameofthron.es","password":"$2b$12$B3DKrkTVNJDlgToXClpcwOJvnKICUsLcrTxNfZIeoqbHIQURsNrXS"}
|
||||
{"_id":{"$oid":"59b99dc3cfa9a34dcd7885d5"},"name":"Gendry","email":"joe_dempsie@gameofthron.es","password":"$2b$12$ctQymjuvXC5dQXYTWX695eJ/0IEXLfXhNiuzad0bL7j8n9YCBq92K"}
|
||||
{"_id":{"$oid":"59b99dc3cfa9a34dcd7885d6"},"name":"Tormund Giantsbane","email":"kristofer_hivju@gameofthron.es","password":"$2b$12$SsfE7EbmV/HH6nii2jJFOe59P91dAV6CqYdGUDOTkNwcPAScUJyVa"}
|
||||
{"_id":{"$oid":"59b99dc5cfa9a34dcd7885d7"},"name":"Gilly","email":"hannah_murray@gameofthron.es","password":"$2b$12$s6/CDf3HFLl3sYNVdOs8sOvdR7HOeQln/ByVQwDGRyTOH5S6qlI7m"}
|
||||
{"_id":{"$oid":"59b99dc5cfa9a34dcd7885d8"},"name":"Brienne of Tarth","email":"gwendoline_christie@gameofthron.es","password":"$2b$12$YjMZPFrj1qS6I/Zy1bxlgOV402ijFcNE.6YVueL5FoWK3eE/QVgKu"}
|
||||
{"_id":{"$oid":"59b99dc5cfa9a34dcd7885d9"},"name":"Ramsay Bolton","email":"iwan_rheon@gameofthron.es","password":"$2b$12$a5CtSXflNAlkWDVmC70vN.06Zds9s3VlnvSVLNM4quXNkF5spOCsa"}
|
||||
{"_id":{"$oid":"59b99dc6cfa9a34dcd7885da"},"name":"Ellaria Sand","email":"indira_varma@gameofthron.es","password":"$2b$12$/sfLmn9AwehR9itBml.p..fKYxUv66om0TallTLMjw2klrmiLwaHy"}
|
||||
{"_id":{"$oid":"59b99dc6cfa9a34dcd7885db"},"name":"Daario Naharis","email":"michiel_huisman@gameofthron.es","password":"$2b$12$22Oqs3Wq.ObJ3Vr68TJKteCSEV1JWIt8jM7/3lf21vOA.jQkdHoBq"}
|
||||
{"_id":{"$oid":"59b99dc7cfa9a34dcd7885dc"},"name":"Missandei","email":"nathalie_emmanuel@gameofthron.es","password":"$2b$12$wMY9mXJCiDZ5dPbgroygBOKjWbuCzv.Snb1sZlp7v41LzyueP/G.S"}
|
||||
{"_id":{"$oid":"59b99dc7cfa9a34dcd7885dd"},"name":"Jaqen H'ghar","email":"tom_wlaschiha@gameofthron.es","password":"$2b$12$sgxhWIzY6UiWvWFRMslCDusielBdf8tpNHraxHAS3c9QNwcCHdHJq"}
|
||||
{"_id":{"$oid":"59b99dc8cfa9a34dcd7885de"},"name":"Tommen Baratheon","email":"dean-charles_chapman@gameofthron.es","password":"$2b$12$POxM5GGAYJNe2phLqcZJ5.3MXEVhUXTQouqvc3hwCU1ZItYbySQsy"}
|
||||
{"_id":{"$oid":"59b99dc9cfa9a34dcd7885df"},"name":"Roose Bolton","email":"michael_mcelhatton@gameofthron.es","password":"$2b$12$JWXzYGip0vvuT40B23mZB.KKoHocgoW2FshxzmhDstZqR23vEtZpS"}
|
||||
{"_id":{"$oid":"59b99dcacfa9a34dcd7885e0"},"name":"The High Sparrow","email":"jonathan_pryce@gameofthron.es","password":"$2b$12$wWkC3fCEuI5X1WoXJft0hOu2qm95MKVmI996/68kXBRUn0HXHebHC"}
|
||||
{"_id":{"$oid":"59b99dcacfa9a34dcd7885e1"},"name":"Grand Maester Pycelle","email":"julian_glover@gameofthron.es","password":"$2b$12$R2KQQQMmjcrbm5XgGdkFJ.38e0I7KptV479H2p1UJ2t5TTb3OSww6"}
|
||||
{"_id":{"$oid":"59b99dcacfa9a34dcd7885e2"},"name":"Meryn Trant","email":"ian_beattie@gameofthron.es","password":"$2b$12$rB95MlNcAdrflKD1gUdiTOg55dbPUtH6po4kKMHGxQjbU9L4k0LBu"}
|
||||
{"_id":{"$oid":"59b99dcbcfa9a34dcd7885e3"},"name":"Hodor","email":"kristian_nairn@gameofthron.es","password":"$2b$12$hFkSycBpMDENs/sT.5y0feifE5IluHUJmYHqH/lSkcc81/HRzzRSq"}
|
||||
{"_id":{"$oid":"59b99dcbcfa9a34dcd7885e4"},"name":"Grenn","email":"mark_stanley@gameofthron.es","password":"$2b$12$gpgDQ2RBHotU4x/ppd0P9ueseDdLTzFHB.4kjkez/ZNerubyFSy1i"}
|
||||
{"_id":{"$oid":"59b99dcccfa9a34dcd7885e5"},"name":"Osha","email":"natalia_tena@gameofthron.es","password":"$2b$12$NpElja7NerH/Vz.6pN0vV.7PNo1fOvMgFx0O8VOro6idM4Evn7n4G"}
|
||||
{"_id":{"$oid":"59b99dcccfa9a34dcd7885e6"},"name":"Rickon Stark","email":"art_parkinson@gameofthron.es","password":"$2b$12$LKBf/wrMe29RwjUCkm6sq.AfuAXshbX6Evys3twd9vaGEsEm6YBqC"}
|
||||
{"_id":{"$oid":"59b99dcdcfa9a34dcd7885e7"},"name":"Ros","email":"esme_bianco@gameofthron.es","password":"$2b$12$dpUAAVPghWXEu0pg0Kv9rOP9bZexMblG911BJzJD/2HOuMat6ZsOe"}
|
||||
{"_id":{"$oid":"59b99dcdcfa9a34dcd7885e8"},"name":"Gregor Clegane","email":"hafthór_júlíus_björnsson@gameofthron.es","password":"$2b$12$6NQKRPtpvs.3w2VuLBgQv.nYBplKlGVK3GRvLqw1n06wO424E.zq6"}
|
||||
{"_id":{"$oid":"59b99dcecfa9a34dcd7885e9"},"name":"Janos Slynt","email":"dominic_carter@gameofthron.es","password":"$2b$12$ssMaPHBLj9tGpLgRXWSCeODrtccHwVbZvDKckjSg1duBLsBZOco8e"}
|
||||
{"_id":{"$oid":"59b99dcecfa9a34dcd7885ea"},"name":"Lancel Lannister","email":"eugene_simon@gameofthron.es","password":"$2b$12$mNWiHoOqOWQser3s6ezqZeTU5vhskTq.K7xkeTA2P.CIfoWsHvonO"}
|
||||
{"_id":{"$oid":"59b99dcecfa9a34dcd7885eb"},"name":"Myrcella Baratheon","email":"nell_tiger_free@gameofthron.es","password":"$2b$12$boJbPqaRG45hQs7jzcwLWu03lGXG9DHIn3rVHcJQ/NK0PaYokP5eu"}
|
||||
{"_id":{"$oid":"59b99dcfcfa9a34dcd7885ec"},"name":"Rodrik Cassel","email":"ron_donachie@gameofthron.es","password":"$2b$12$dIvO2KpkHkje98eMZg.exuDR.MeOkHlRC9R7PTKj1D66PhX4NaDP6"}
|
||||
{"_id":{"$oid":"59b99dcfcfa9a34dcd7885ed"},"name":"Maester Luwin","email":"donald_sumpter@gameofthron.es","password":"$2b$12$K9m5hh0Lh.NtYqRpxF40NeWTRwOM7nPp4NJL5v/9fZZ/vpIWKN3KO"}
|
||||
{"_id":{"$oid":"59b99dcfcfa9a34dcd7885ee"},"name":"Irri","email":"amrita_acharia@gameofthron.es","password":"$2b$12$mTvd3eFqgflqO74rS95zKOFU3wKRe5alg.iM23AknNnpZ/TdT95eK"}
|
||||
{"_id":{"$oid":"59b99dd0cfa9a34dcd7885ef"},"name":"Doreah","email":"roxanne_mckee@gameofthron.es","password":"$2b$12$3M34QX9A/7jNLn9neSddUeW5oJfcl5OYOqYUL.7L87/ThA8Xbfug6"}
|
||||
{"_id":{"$oid":"59b99dd0cfa9a34dcd7885f0"},"name":"Kevan Lannister","email":"ian_gelder@gameofthron.es","password":"$2b$12$YB/GLht749jn9jxcwOnw4.ZekNoiSzmS8qS.raqFzZPrNbBJAB20O"}
|
||||
{"_id":{"$oid":"59b99dd1cfa9a34dcd7885f1"},"name":"Barristan Selmy","email":"ian_mcelhinney@gameofthron.es","password":"$2b$12$IabcnI3C6lUTfq2Ez5f0bOEsM6Hok6JsPMyTxnVHwZGIEaHtpohsy"}
|
||||
{"_id":{"$oid":"59b99dd6cfa9a34dcd7885f2"},"name":"Rast","email":"luke_barnes@gameofthron.es","password":"$2b$12$wzKOV4fkmI5hfiQLFYpSDePsSBqenWs8CpI1N7OcD1A.3NF98adqy"}
|
||||
{"_id":{"$oid":"59b99dd6cfa9a34dcd7885f3"},"name":"Maester Aemon","email":"peter_vaughan@gameofthron.es","password":"$2b$12$uOefAK8L28vlzZ9lsZV2Q.LplAND.FPwKHPmZ7wgXeO/F0mbVR1b2"}
|
||||
{"_id":{"$oid":"59b99dd6cfa9a34dcd7885f4"},"name":"Pypar","email":"josef_altin@gameofthron.es","password":"$2b$12$GTKOrQ2gHc1o0OE37ub6d.yKxI4o9RU/72kPAbiaUbqkrANKYO34W"}
|
||||
{"_id":{"$oid":"59b99dd7cfa9a34dcd7885f5"},"name":"Alliser Thorne","email":"owen_teale@gameofthron.es","password":"$2b$12$IWJV4xTZ4dyBsvwQQ2FlF.yw3Mfy.XZCOsprt6kaLRtHu9k6ZHbx."}
|
||||
{"_id":{"$oid":"59b99dd7cfa9a34dcd7885f6"},"name":"Othell Yarwyck","email":"brian_fortune@gameofthron.es","password":"$2b$12$RfLlYF.8Vxj4MXILL2kvIuyuAO8rN3KR6//UL1a6rNIfNgBaASS66"}
|
||||
{"_id":{"$oid":"59b99dd8cfa9a34dcd7885f7"},"name":"Loras Tyrell","email":"finn_jones@gameofthron.es","password":"$2b$12$Eb5TLqYLS74pLP9r.2agNe56ht1dvFkQOCODxku8KQmLfldBGa7Cu"}
|
||||
{"_id":{"$oid":"59b99dd8cfa9a34dcd7885f8"},"name":"Hot Pie","email":"ben_hawkey@gameofthron.es","password":"$2b$12$o99XQuQRvutjESJ8/eqnWe4w8aCYXHFF1cJmZdeKs6acmoPaVlCK."}
|
||||
{"_id":{"$oid":"59b99dd8cfa9a34dcd7885f9"},"name":"Beric Dondarrion","email":"richard_dormer@gameofthron.es","password":"$2b$12$CHeWRV3bBssK0MR1o4FLcOCmFLaPIPTA0KzKI0aWYDnXCKm98MbJy"}
|
||||
{"_id":{"$oid":"59b99dd9cfa9a34dcd7885fa"},"name":"Podrick Payne","email":"daniel_portman@gameofthron.es","password":"$2b$12$yYDEeKYMkE2zDjP35/RfZONzFZEuv026MnSRAJ5ZPUoBUhvu6ZRN."}
|
||||
{"_id":{"$oid":"59b99dd9cfa9a34dcd7885fb"},"name":"Eddison Tollett","email":"ben_crompton@gameofthron.es","password":"$2b$12$adD4J5Cnk/aeVdKC3qnD7ufw7S9sTrvWoiSxNkLqZsr0SWjFj91Wq"}
|
||||
{"_id":{"$oid":"59b99ddacfa9a34dcd7885fc"},"name":"Yara Greyjoy","email":"gemma_whelan@gameofthron.es","password":"$2b$12$q4rJ2PG4ZJZ1c9PNJeZU1uHH/ckwCh4P0xfu6lGgHIQ8/ugptuQuK"}
|
||||
{"_id":{"$oid":"59b99ddacfa9a34dcd7885fd"},"name":"Selyse Baratheon","email":"tara_fitzgerald@gameofthron.es","password":"$2b$12$Ri/w5TEI/CsWxvdscYkzhuVzKF0Zy98zgDWO5pmVsXb05jki5PKrG"}
|
||||
{"_id":{"$oid":"59b99ddacfa9a34dcd7885fe"},"name":"Grey Worm","email":"jacob_anderson@gameofthron.es","password":"$2b$12$Kplgm66WrJlrIxV7g.uQj.zSSY3Q/GuznI6i9z5I9abqcszpTGc0O"}
|
||||
{"_id":{"$oid":"59b99ddbcfa9a34dcd7885ff"},"name":"Qyburn","email":"anton_lesser@gameofthron.es","password":"$2b$12$Aogz..TkpBMB5UFfgIRSP.dy7DX9qgOi587FSORqRWqApfbw3x7wy"}
|
||||
{"_id":{"$oid":"59b99ddbcfa9a34dcd788600"},"name":"Olenna Tyrell","email":"diana_rigg@gameofthron.es","password":"$2b$12$8Oh3DVnn8e5NK9nHtX4ZVeprB3O6Zrb8l8KxT2l3rraW11HhxH3di"}
|
||||
{"_id":{"$oid":"59b99ddbcfa9a34dcd788601"},"name":"Shireen Baratheon","email":"kerry_ingram@gameofthron.es","password":"$2b$12$F8VweX6dNiq4Gymmc7LJsu5U1G0d0wxaf/95CVl5w/4..mFfdgqdG"}
|
||||
{"_id":{"$oid":"59b99ddbcfa9a34dcd788602"},"name":"Meera Reed","email":"ellie_kendrick@gameofthron.es","password":"$2b$12$SdyXPBMdGScx6DePpPawFeOqcpiwjdHAuTXaPl0mkvWeLzZk6EWTi"}
|
||||
{"_id":{"$oid":"59b99dddcfa9a34dcd788603"},"name":"Jojen Reed","email":"thomas_brodie-sangster@gameofthron.es","password":"$2b$12$ZAJ8OFWUFNdxhc0xyTd42evQJfL7FnEdk3koHwYtHpDqsrZI61XP."}
|
||||
{"_id":{"$oid":"59b99dddcfa9a34dcd788604"},"name":"Thoros of Myr","email":"paul_kaye@gameofthron.es","password":"$2b$12$bkA1MM3UEwZ4N0VpCQY68eMY8HKTHWtk2xI2QnG4MuW5UWHlBrF8G"}
|
||||
{"_id":{"$oid":"59b99ddecfa9a34dcd788605"},"name":"Olly","email":"brenock_o'connor@gameofthron.es","password":"$2b$12$Mp0mG3u/6xuQSe/3/UjO8uHTHUDQUIcV0Iki42vfAqKLaBbYxHjv."}
|
||||
{"_id":{"$oid":"59b99ddecfa9a34dcd788606"},"name":"Mace Tyrell","email":"roger_ashton-griffiths@gameofthron.es","password":"$2b$12$Z7BRen4BsJqxnBlsRupWou2DlT7CQameOt7V9UlV0vWw3Z2B9sDj6"}
|
||||
{"_id":{"$oid":"59b99ddecfa9a34dcd788607"},"name":"The Waif","email":"faye_marsay@gameofthron.es","password":"$2b$12$JGlWYUPkZ3xryO9h4x4wdOsnbuLdzbSMSCaJENY6LaLfWYIl86xdG"}
|
||||
{"_id":{"$oid":"59b99ddfcfa9a34dcd788608"},"name":"Bowen Marsh","email":"michael_condron@gameofthron.es","password":"$2b$12$G8bl4haz.de9f1ohneIcIus3GCj4nNNP7WiufQy6.aoIh01AVk2Xq"}
|
||||
{"_id":{"$oid":"59b99ddfcfa9a34dcd788609"},"name":"Richard Davis","email":"richard_davis@fakegmail.com","password":"$2b$12$q5/117rbpGoczEDK5LcDjeeOmOnzkVi6h2VIN.1Dbugn6Y5kOo4Ja"}
|
||||
{"_id":{"$oid":"59b99ddfcfa9a34dcd78860a"},"name":"Greg Powell","email":"greg_powell@fakegmail.com","password":"$2b$12$XpveUB6kIiU3zG5aABw26OitIB7cDBbSUWJAz4WDF4XXyNNJ/mp76"}
|
||||
{"_id":{"$oid":"59b99de0cfa9a34dcd78860b"},"name":"Sarah Lewis","email":"sarah_lewis@fakegmail.com","password":"$2b$12$5kCUjcP3lvYSzhouVJTpOeCZ7e7Xke8gDoPPg2Uyz39tNKrp9om1a"}
|
||||
{"_id":{"$oid":"59b99de0cfa9a34dcd78860c"},"name":"Ronald Cox","email":"ronald_cox@fakegmail.com","password":"$2b$12$HhDeE1teAaNqj2Mrfn4f2O57K8z6kVVqtCEr.7Qc5BZR69H6XwRlK"}
|
||||
{"_id":{"$oid":"59b99de0cfa9a34dcd78860d"},"name":"Emily Ellis","email":"emily_ellis@fakegmail.com","password":"$2b$12$UuCb5RqPEgheoLlwOF/Jb.x9gpFVmD30oUwpSRKljwo8pBUmWT6eG"}
|
||||
{"_id":{"$oid":"59b99de1cfa9a34dcd78860e"},"name":"Victor Patel","email":"victor_patel@fakegmail.com","password":"$2b$12$VyWh4xdBtuZrhuR933GY6evfU7.py2dJIP9wuSmeiJ.94iP0EO4Pq"}
|
||||
{"_id":{"$oid":"59b99de1cfa9a34dcd78860f"},"name":"Karina Martin","email":"karina_martin@fakegmail.com","password":"$2b$12$s6XOIsF9p9/p6tZd0nZ1ee5qd6/nc5sL8dd0iES0ZEJySgacjcqD."}
|
||||
{"_id":{"$oid":"59b99de2cfa9a34dcd788610"},"name":"Robert Jordan","email":"robert_jordan@fakegmail.com","password":"$2b$12$OumeM9/x5dBn5RLd/5QUNu8poyzsVbhJtLs2S02JqCwzubbbBK902"}
|
||||
{"_id":{"$oid":"59b99de2cfa9a34dcd788611"},"name":"Javier Smith","email":"javier_smith@fakegmail.com","password":"$2b$12$ce2znqUW43.BjKQaTS5tiekhqZuCLQHOguozLkVm4P.WM8VlrEhPe"}
|
||||
{"_id":{"$oid":"59b99de2cfa9a34dcd788612"},"name":"Amy Phillips","email":"amy_phillips@fakegmail.com","password":"$2b$12$z.IU36O/1r25xdhI.Gdw1e2dLXSjIgIMNrxginP0/iVIlZcCWiyaK"}
|
||||
{"_id":{"$oid":"59b99de3cfa9a34dcd788613"},"name":"Jason Smith","email":"jason_smith@fakegmail.com","password":"$2b$12$l2JMT18BcA8.R3tUxVDKj.9/jwre8CAccr21PvJ576nJ8Pvegxn0m"}
|
||||
{"_id":{"$oid":"59b99de3cfa9a34dcd788614"},"name":"Cameron Duran","email":"cameron_duran@fakegmail.com","password":"$2b$12$50w2j63ATGmhVOh2rgdjv.wOd9TV0Jb9Xk/Anms0fxVSvGMf5MwvK"}
|
||||
{"_id":{"$oid":"59b99de3cfa9a34dcd788615"},"name":"Megan Turner","email":"megan_turner@fakegmail.com","password":"$2b$12$nR8x.s7PmEQttaF7RS33euSLEZzuu0G2UhSK.PeHJEZEjcK.J3Xq6"}
|
||||
{"_id":{"$oid":"59b99de4cfa9a34dcd788616"},"name":"Megan Richards","email":"megan_richards@fakegmail.com","password":"$2b$12$iDxjjcgBA.Q9zjTlOD4KJuhPJx6gw5GecbDWCbVmfzzv2rqNbC2vC"}
|
||||
{"_id":{"$oid":"59b99de4cfa9a34dcd788617"},"name":"Thomas Buckley","email":"thomas_buckley@fakegmail.com","password":"$2b$12$.zRRXpjiT0uuR13kt85CDesUMJPIEK1mziudzedd7S10YVAd31586"}
|
||||
{"_id":{"$oid":"59b99de4cfa9a34dcd788618"},"name":"Lisa Rasmussen","email":"lisa_rasmussen@fakegmail.com","password":"$2b$12$HHK6sMwGNXZlOHOpFXcHpuS3qS8/XA2202y7ZIlTJ.6y5E6SUl7Yy"}
|
||||
{"_id":{"$oid":"59b99de5cfa9a34dcd788619"},"name":"Connie Johnson","email":"connie_johnson@fakegmail.com","password":"$2b$12$tA3NXW5mHAru7YbIrW6x3.T3OweDVjBwk6wf/ukXBiwxAZXi3R5m2"}
|
||||
{"_id":{"$oid":"59b99de5cfa9a34dcd78861a"},"name":"Victor Fleming","email":"victor_fleming@fakegmail.com","password":"$2b$12$DQSGcwfMllp0HTDNI6QLGeI41zrqprdlEnIXf6RHdpOCMBc37wzV."}
|
||||
{"_id":{"$oid":"59b99de6cfa9a34dcd78861b"},"name":"Brandon Hardy","email":"brandon_hardy@fakegmail.com","password":"$2b$12$7qxHDP2xlgztpQITlwjlBugE2ned0nRmm22Gu1mK34fZJvh5IE4SO"}
|
||||
{"_id":{"$oid":"59b99de6cfa9a34dcd78861c"},"name":"Kathryn Sosa","email":"kathryn_sosa@fakegmail.com","password":"$2b$12$naMKKiQlGxdNh1WMCa6ws.Yo1nEr5OWBILzMYEDlt.fw.UmOVnMhu"}
|
||||
{"_id":{"$oid":"59b99de6cfa9a34dcd78861d"},"name":"Mrs. Ariana Nunez","email":"mrs._ariana_nunez@fakegmail.com","password":"$2b$12$KN9tlEa1K65zgHHG7zh2KePPpU0/NC1o/WN3RoIOaHBvWEoPq2DMC"}
|
||||
{"_id":{"$oid":"59b99de7cfa9a34dcd78861e"},"name":"Yvette Roth","email":"yvette_roth@fakegmail.com","password":"$2b$12$JmceK9VLl7aY/uF9.ZdLTOuj0y5xR3jjvDZVyFCCPQT/lly5IocIm"}
|
||||
{"_id":{"$oid":"59b99de7cfa9a34dcd78861f"},"name":"Kelsey Smith","email":"kelsey_smith@fakegmail.com","password":"$2b$12$S.moHRDfHWLM.F5IasBPQek/y76l0ejX.a5EnPQMbtpECI3tWXS/y"}
|
||||
{"_id":{"$oid":"59b99de7cfa9a34dcd788620"},"name":"Keith Phillips","email":"keith_phillips@fakegmail.com","password":"$2b$12$oXW3cr3lIY37/Ps3uSZBj.rFQoFjZAuFvtHNyxHyocIIlI9lT93MO"}
|
||||
{"_id":{"$oid":"59b99de7cfa9a34dcd788621"},"name":"Morgan Smith","email":"morgan_smith@fakegmail.com","password":"$2b$12$vm836TjgawCzAglcRq/GWOPJpAOT9W.w0tEAGqoIvDxMRn.rfZCQK"}
|
||||
{"_id":{"$oid":"59b99de8cfa9a34dcd788622"},"name":"Anthony Thompson","email":"anthony_thompson@fakegmail.com","password":"$2b$12$Ki.7nartO8MscZ53cV5jEuLa83JD8OKd6sgCqxird98ijmWRTRcrC"}
|
||||
{"_id":{"$oid":"59b99de8cfa9a34dcd788623"},"name":"Joshua Kent","email":"joshua_kent@fakegmail.com","password":"$2b$12$xSofV4dlicgiRA9yRtB9BescTvQFusNdde7/yz6AQ8lRKKMTdhRLW"}
|
||||
{"_id":{"$oid":"59b99deacfa9a34dcd788624"},"name":"Brenda Martin","email":"brenda_martin@fakegmail.com","password":"$2b$12$H.QWgwnd5SwchVniifWfS.BmBefv6FhBBKqjcDlI20ZdqgFvIy3F2"}
|
||||
{"_id":{"$oid":"59b99deacfa9a34dcd788625"},"name":"Garrett Obrien","email":"garrett_obrien@fakegmail.com","password":"$2b$12$ElY14tB9rHL3L4yhrY7gcOGr0u0eFZ5Eb6IoG3eH15sqAeAqbco/a"}
|
||||
{"_id":{"$oid":"59b99deacfa9a34dcd788626"},"name":"Lori Franklin","email":"lori_franklin@fakegmail.com","password":"$2b$12$h25/G5rXZejwsAhn7rvYIuuLzwnayZcf4yX0CV02gDh0dA14UyVsy"}
|
||||
{"_id":{"$oid":"59b99debcfa9a34dcd788627"},"name":"Kenneth Chandler","email":"kenneth_chandler@fakegmail.com","password":"$2b$12$Bo8ObYfsGdSsJrcdf/bat.NFhp4ITDrsyZvYlTmZWh.zrReVKVH4u"}
|
||||
{"_id":{"$oid":"59b99debcfa9a34dcd788628"},"name":"Daniel Simmons","email":"daniel_simmons@fakegmail.com","password":"$2b$12$o2vaieyGbqZ5a.BhIB3e9.cZ1dEO3Ob/3gc1Ef1/QX4cI9vnMraUC"}
|
||||
{"_id":{"$oid":"59b99debcfa9a34dcd788629"},"name":"Paula Sullivan","email":"paula_sullivan@fakegmail.com","password":"$2b$12$6eM.dlL7Wi84eYUkwzkU.erG/JqAvwOKSGn5V1bG6HLfIFrpTYaXi"}
|
||||
{"_id":{"$oid":"59b99deccfa9a34dcd78862a"},"name":"Richard Schmidt","email":"richard_schmidt@fakegmail.com","password":"$2b$12$3odZLmzPAoFZc/S3mVRCWOimTOx.RGTY1CP/jJBsW42F0zfbwOXQK"}
|
||||
{"_id":{"$oid":"59b99deccfa9a34dcd78862b"},"name":"Anthony Smith","email":"anthony_smith@fakegmail.com","password":"$2b$12$OLhPk6TMdQ9rY/LIMjsaa.Pfb6IlCQgZK2BCx37lYqotgy9tHo3F6"}
|
||||
{"_id":{"$oid":"59b99dedcfa9a34dcd78862c"},"name":"Michael Day","email":"michael_day@fakegmail.com","password":"$2b$12$1BdlPh4Imkw8kn7aCgEWsOCt1DED7cFTMlVOf62k6lGxEvQEe1L56"}
|
||||
{"_id":{"$oid":"59b99dedcfa9a34dcd78862d"},"name":"Mercedes Tyler","email":"mercedes_tyler@fakegmail.com","password":"$2b$12$ONDwIwR9NKF1Tp5GjGI12e8OFMxPELoFrk4x4Q3riJGWY6jl/UZAa"}
|
||||
{"_id":{"$oid":"59b99dedcfa9a34dcd78862e"},"name":"Kristen Schmidt","email":"kristen_schmidt@fakegmail.com","password":"$2b$12$lUexqpKoc6RNXLAHGPZ50OLWr3oKfrJW9Vg.q6s7DrCs5X0blJYtW"}
|
||||
{"_id":{"$oid":"59b99deecfa9a34dcd78862f"},"name":"Justin Williams","email":"justin_williams@fakegmail.com","password":"$2b$12$5GAeUijkM4g3s5yBZniXxOYlA13vLLt.CPkXLCs3jlfsYJrgJ37fy"}
|
||||
{"_id":{"$oid":"59b99deecfa9a34dcd788630"},"name":"John Roman","email":"john_roman@fakegmail.com","password":"$2b$12$UW2RqzQlgLcPNLn3gxY16uMhqso5GgeAzYfAQVY2yplhacxZ.daSy"}
|
||||
{"_id":{"$oid":"59b99defcfa9a34dcd788631"},"name":"April Cole","email":"april_cole@fakegmail.com","password":"$2b$12$DhQx.0ywiZK7v4UrN6YeXuS06U2JHNM2owUHxbL8aXlobGT7E65Ke"}
|
||||
{"_id":{"$oid":"59b99defcfa9a34dcd788632"},"name":"Kimberly Gates","email":"kimberly_gates@fakegmail.com","password":"$2b$12$fE/FzdNHaDJS2nW5jPziHe0lgKcVqPEF6B2X7vCx35RgvEVp2DS7y"}
|
||||
{"_id":{"$oid":"59b99defcfa9a34dcd788633"},"name":"Denise Davidson","email":"denise_davidson@fakegmail.com","password":"$2b$12$kjWPMnQwGlwe7NGI0NdE9uq3KGvJ8jA0bJILkEUXFE9tzPVjwzJ1a"}
|
||||
{"_id":{"$oid":"59b99df0cfa9a34dcd788634"},"name":"Michael Moore","email":"michael_moore@fakegmail.com","password":"$2b$12$9rCFOeptsZ6eFBzoprKRFOKS.NQteHtfWurzBkndHNt9DLVdAZGsW"}
|
||||
{"_id":{"$oid":"59b99df0cfa9a34dcd788635"},"name":"Lisa Silva","email":"lisa_silva@fakegmail.com","password":"$2b$12$K8ZpLpGQUUFev/fxmJSlueIdVJ3.7CNYRNERCRae5B1auB7SLBTu2"}
|
||||
{"_id":{"$oid":"59b99df0cfa9a34dcd788636"},"name":"Andrea Le","email":"andrea_le@fakegmail.com","password":"$2b$12$JS87HWuL2y0P1E6kYrcbKOKx22.wsKEdLtS0F734/vKdhuduLM8Ve"}
|
||||
{"_id":{"$oid":"59b99df1cfa9a34dcd788637"},"name":"Edward Barrett","email":"edward_barrett@fakegmail.com","password":"$2b$12$Jzx8f0IiHYFcdU/PEceFJeS1HjC43HTL2aBhKQt8uUM2zfJf3p7Ki"}
|
||||
{"_id":{"$oid":"59b99df1cfa9a34dcd788638"},"name":"Christian Williams","email":"christian_williams@fakegmail.com","password":"$2b$12$D2/B/KGdHRduXiT0/OX5Yu0YMfubTWOOaCjuOyQrDUMvq2Eju10ny"}
|
||||
{"_id":{"$oid":"59b99df2cfa9a34dcd788639"},"name":"Jason Hernandez","email":"jason_hernandez@fakegmail.com","password":"$2b$12$fmvh3F8TRhntCXSCTb/oG.MJlZmXwStdf/UfCSFnSxSsbJb0Bsmwi"}
|
||||
{"_id":{"$oid":"59b99df2cfa9a34dcd78863a"},"name":"Patricia Good","email":"patricia_good@fakegmail.com","password":"$2b$12$t9xIBFolWLphJBO9VCpV4uoZDx/TOhg7N436kBe72hgDMxsGvQr3m"}
|
||||
{"_id":{"$oid":"59b99df2cfa9a34dcd78863b"},"name":"Barbara Gonzalez","email":"barbara_gonzalez@fakegmail.com","password":"$2b$12$qxLcDfjy7RdjfJbrFRHntu0kzVnXzJKED0on8TZ84dLlSCKKkaJt2"}
|
||||
{"_id":{"$oid":"59b99df3cfa9a34dcd78863c"},"name":"Denise Bryant","email":"denise_bryant@fakegmail.com","password":"$2b$12$Dcm7ncpCt0PVR4HFux4hDetCNL3E3mQg9GKqJHR/Nz/O40HCgEJzu"}
|
||||
{"_id":{"$oid":"59b99df4cfa9a34dcd78863d"},"name":"Victoria Sanders","email":"victoria_sanders@fakegmail.com","password":"$2b$12$/2aikvro4gXgcp01Z8qIj.s2s53lpVcLQRbG/9VNbHa4i3ajo5dc."}
|
||||
{"_id":{"$oid":"59b99df4cfa9a34dcd78863e"},"name":"Taylor Scott","email":"taylor_scott@fakegmail.com","password":"$2b$12$rIJO4MKGZFHKyPeU9X8hSOsCjL3Isa9Gv8rZ7rzM7kKA3XUd1PAlO"}
|
||||
{"_id":{"$oid":"59b99df5cfa9a34dcd78863f"},"name":"Taylor Hill","email":"taylor_hill@fakegmail.com","password":"$2b$12$5NRO3TpZti62ZN2rSlxYoOurfMQAUEQ4oIufrfAhcsSqGp4eKF4Gi"}
|
||||
{"_id":{"$oid":"59b99df5cfa9a34dcd788640"},"name":"Melissa Jones","email":"melissa_jones@fakegmail.com","password":"$2b$12$S6.mFqBn8QMRtyeJUJbRcOwkrgtjHyg7GkmxilnWvOzRtPar.d1K."}
|
||||
{"_id":{"$oid":"59b99df5cfa9a34dcd788641"},"name":"Christopher Robinson","email":"christopher_robinson@fakegmail.com","password":"$2b$12$Bop6XQ2mLRjsMXPjKUEtcuIw9751lV.cKj/eXM1ZwSetsku3sa04W"}
|
||||
{"_id":{"$oid":"59b99df6cfa9a34dcd788642"},"name":"Amy Ramirez","email":"amy_ramirez@fakegmail.com","password":"$2b$12$LN9OzMA5sX3bQnMjkkWa.OjMrjif.LIbqx7YSf52FtQ9QcBlUS8ee"}
|
||||
{"_id":{"$oid":"59b99df7cfa9a34dcd788643"},"name":"Phillip Collins","email":"phillip_collins@fakegmail.com","password":"$2b$12$3XQmnWfaMh9bwJMXAdJLheLLiU7bCVATlDsdo4BREnIQFbfCxUOcK"}
|
||||
{"_id":{"$oid":"59b99df7cfa9a34dcd788644"},"name":"Jerry Cabrera","email":"jerry_cabrera@fakegmail.com","password":"$2b$12$HEimsC0UBidI9AYqPU4Mr.P8UZVO6zsZm2VUFVeuA467fdqp8WJDu"}
|
||||
{"_id":{"$oid":"59b99df7cfa9a34dcd788645"},"name":"Ms. Cathy Miller","email":"ms._cathy_miller@fakegmail.com","password":"$2b$12$wQ02A.LLpeLLEItcBZF2IOOSlds3VjdaXOI2XRt/ElyG2852ITbiW"}
|
||||
{"_id":{"$oid":"59b99df8cfa9a34dcd788646"},"name":"Lisa Russo","email":"lisa_russo@fakegmail.com","password":"$2b$12$pOdj440b9rps82eCfXzCiONHjBo9zowp62kNDdQSRVPMwGJmxAk0W"}
|
||||
{"_id":{"$oid":"59b99df8cfa9a34dcd788647"},"name":"Thomas Morris","email":"thomas_morris@fakegmail.com","password":"$2b$12$IfMqv/fVHb3KZtQxKtUXP.C.Uh9rNI9qKWB4eZ6d2YiEl5P3XnDk."}
|
||||
{"_id":{"$oid":"59b99df8cfa9a34dcd788648"},"name":"Elizabeth Wiggins","email":"elizabeth_wiggins@fakegmail.com","password":"$2b$12$UGbyi1WBFHu9xqTYp2nxzuGtWaolgxyj/7r2kXjSltr7s8jzr8RFm"}
|
||||
{"_id":{"$oid":"59b99df9cfa9a34dcd788649"},"name":"Nicholas Webster","email":"nicholas_webster@fakegmail.com","password":"$2b$12$LLuOi5eMoy6hWIC61dolKu9/0bxRKsL0kwWfcJ8A0qr.SX/AR5aCi"}
|
||||
{"_id":{"$oid":"59b99df9cfa9a34dcd78864a"},"name":"Teresa Thomas","email":"teresa_thomas@fakegmail.com","password":"$2b$12$vQQlmv3ubYNZh8HfSXmu4.peazChIJo15UEnLpQz9O90nr8U/qlfS"}
|
||||
{"_id":{"$oid":"59b99df9cfa9a34dcd78864b"},"name":"Catherine Romero","email":"catherine_romero@fakegmail.com","password":"$2b$12$XVWuCkFmEypxLhpe6OnZdeZ2HcO/mD.q0bcDun5izEPMDCSTGW5AO"}
|
||||
{"_id":{"$oid":"59b99dfacfa9a34dcd78864c"},"name":"Julia Nichols","email":"julia_nichols@fakegmail.com","password":"$2b$12$HZbkbktkRTaV7LiwLxW3D.gDV5lQAy05Wumz981D7gwvSoAc9uJxq"}
|
||||
{"_id":{"$oid":"59b99dfacfa9a34dcd78864d"},"name":"Heather Leonard","email":"heather_leonard@fakegmail.com","password":"$2b$12$/mzEsE5kIBX1sWGWlp4GuOilNW.h5ZSIWVgYh.kbt3i0LG3BPY3hy"}
|
||||
{"_id":{"$oid":"59b99dfbcfa9a34dcd78864e"},"name":"Melissa Young","email":"melissa_young@fakegmail.com","password":"$2b$12$iei9pWuCZ6wF/TJhVJ1gE.k7dkc.0NiHgR6/lJCn4ANkaBkdKS/Wy"}
|
||||
{"_id":{"$oid":"59b99dfbcfa9a34dcd78864f"},"name":"John Rice","email":"john_rice@fakegmail.com","password":"$2b$12$Yg0bT/yCT5fX8xn.D4Fj3.slpd7tccYWKgRGghrLglX5Faz6Fb86G"}
|
||||
{"_id":{"$oid":"59b99dfccfa9a34dcd788650"},"name":"Blake Sellers","email":"blake_sellers@fakegmail.com","password":"$2b$12$g2u20yqqpzbNipA6lfIoBO3Cs9jM7jsWBhDheF1OsthHpLfEcD2Gm"}
|
||||
{"_id":{"$oid":"59b99dfdcfa9a34dcd788651"},"name":"Theresa Holmes","email":"theresa_holmes@fakegmail.com","password":"$2b$12$1b.0k6/Ox.r9CHmPYPIs2eH5FZolXLc5e9E4IyTJd3YkzAVTB1Dta"}
|
||||
{"_id":{"$oid":"59b99dfdcfa9a34dcd788652"},"name":"Bradley Brooks","email":"bradley_brooks@fakegmail.com","password":"$2b$12$YvZMPevRPXozhmujYwhFe.oTEHhdvHrJEviyXaXUjLsDr6tkHBoC."}
|
||||
{"_id":{"$oid":"59b99dfdcfa9a34dcd788653"},"name":"Thomas Green","email":"thomas_green@fakegmail.com","password":"$2b$12$6u6dECDnaDoNehg1gU14KOcGAtmMnKcnsSv7U2W693xk/UTKF.of6"}
|
||||
{"_id":{"$oid":"59b99dfecfa9a34dcd788654"},"name":"Jonathon Mccullough","email":"jonathon_mccullough@fakegmail.com","password":"$2b$12$uZlaQmlnL501KsvPJSCJbO47tz9.8GB8Hl0Xu31xURToXMP8dWzOi"}
|
||||
{"_id":{"$oid":"59b99dfecfa9a34dcd788655"},"name":"Jeffrey Roberts","email":"jeffrey_roberts@fakegmail.com","password":"$2b$12$UrTFJ6Xnr043.QRwFVlqgudHC6GPSjejaldJw2/UFsR.dyPwj7cxK"}
|
||||
{"_id":{"$oid":"59b99dfecfa9a34dcd788656"},"name":"Jose Hall","email":"jose_hall@fakegmail.com","password":"$2b$12$ghmMMtvS1Wcmf9.UEF5ep.sAU5KS2.GUpgK41hiPh4EzyJYCy2P42"}
|
||||
{"_id":{"$oid":"59b99e00cfa9a34dcd788657"},"name":"Jennifer Frazier","email":"jennifer_frazier@fakegmail.com","password":"$2b$12$Xm1ktF5woIqEw5q00xCnZO.PwJDWi9VIrbbrMemqv5zzF1zJGN2AC"}
|
||||
{"_id":{"$oid":"59b99e00cfa9a34dcd788658"},"name":"Jamie Santana","email":"jamie_santana@fakegmail.com","password":"$2b$12$KhXBuPIzyxoqMjpTn4h4ku9Dky3bofFDVNrMD5T6Z2Dd1j1wWAGe2"}
|
||||
{"_id":{"$oid":"59b99e01cfa9a34dcd788659"},"name":"Anthony Cline","email":"anthony_cline@fakegmail.com","password":"$2b$12$JWTRRBJgXOv.peG2HDFHeORuwvOaZigFtxhUSDhbpPEFRRuhS19F2"}
|
||||
{"_id":{"$oid":"59b99e01cfa9a34dcd78865a"},"name":"Donna Russell","email":"donna_russell@fakegmail.com","password":"$2b$12$5PICbqGRxD2Mj5ljv0wQnu6d.a4mNPoma1GtMvYOHE.M7bz6vIu4e"}
|
||||
{"_id":{"$oid":"59b99e02cfa9a34dcd78865b"},"name":"Blake Fitzgerald","email":"blake_fitzgerald@fakegmail.com","password":"$2b$12$.ilQEC/iyR4FhnMA1PmzVe.kMkAbI7htSZJKquTjnaVFH.RDmsP32"}
|
||||
{"_id":{"$oid":"59b99e02cfa9a34dcd78865c"},"name":"Mary Mitchell","email":"mary_mitchell@fakegmail.com","password":"$2b$12$rT8TmryDDeU446M.g1vVCePtByl85Y/vZ/awAn3eOXCke.bKXHr9G"}
|
||||
{"_id":{"$oid":"59b99e02cfa9a34dcd78865d"},"name":"Deborah Kennedy","email":"deborah_kennedy@fakegmail.com","password":"$2b$12$lJL2fO48ZrLRhZTf1FBVv.eaaQQ6FSSUh/SwAqvRkcCgM1lZp4moG"}
|
||||
{"_id":{"$oid":"59b99e02cfa9a34dcd78865e"},"name":"Lori Blankenship","email":"lori_blankenship@fakegmail.com","password":"$2b$12$SQUa.3cIKcazfuUOpd9/huR.VeFAH.uR.ESvIMfbMW1YQjZx47Tw6"}
|
||||
{"_id":{"$oid":"59b99e03cfa9a34dcd78865f"},"name":"Paul Bailey","email":"paul_bailey@fakegmail.com","password":"$2b$12$m4x95MQ5iSqH.SmcxmBeOuiDYUi9iMcjT1VHXiwKBPHtQ9MNrKnru"}
|
||||
{"_id":{"$oid":"59b99e03cfa9a34dcd788660"},"name":"John Bishop","email":"john_bishop@fakegmail.com","password":"$2b$12$ifnm6ZFlRQaV4YFe2WcpKuyYfp2eW.42QECH7dkEoD0WeTFpQ8pCe"}
|
||||
{"_id":{"$oid":"59b99e04cfa9a34dcd788661"},"name":"Nichole Miller","email":"nichole_miller@fakegmail.com","password":"$2b$12$RwG1XZMs3MT/kfdH0L2EWOrfUkOuDkMl./KT.xld4Wyie9w87CM1a"}
|
||||
{"_id":{"$oid":"59b99e04cfa9a34dcd788662"},"name":"Yolanda Owen","email":"yolanda_owen@fakegmail.com","password":"$2b$12$lmpyYO8lCI.Y/J5AZF6/4u8XyEnCoZXsZzf7l9f7ECNbktqH2KZO."}
|
||||
{"_id":{"$oid":"59b99e04cfa9a34dcd788663"},"name":"Nicholas Johnson","email":"nicholas_johnson@fakegmail.com","password":"$2b$12$hdzNySj4l/tZR4op5oQXb.FStH3u7ZHjmhhtrpQFIEe39NkBS6R1y"}
|
||||
{"_id":{"$oid":"59b99e05cfa9a34dcd788664"},"name":"Desiree Pierce","email":"desiree_pierce@fakegmail.com","password":"$2b$12$6ndntifLUo9dshFeTkyOEO.xskWXa1n2q5dcl9uOglKz3cd0vMeJm"}
|
||||
{"_id":{"$oid":"59b99e06cfa9a34dcd788665"},"name":"Connie Barton","email":"connie_barton@fakegmail.com","password":"$2b$12$dFHzE0VmGHX7K7Je4QWZ0ucv4XX7zup9FWvrF8NFUHlm4k2a4z2se"}
|
||||
{"_id":{"$oid":"59b99e06cfa9a34dcd788666"},"name":"Patrick Knight","email":"patrick_knight@fakegmail.com","password":"$2b$12$GrKhwH1qeeJNGcGLmjg9f.k7ruCRxGUbfm4z3mgzGkiXXZVvKGCwy"}
|
||||
{"_id":{"$oid":"59b99e07cfa9a34dcd788667"},"name":"Eric Navarro","email":"eric_navarro@fakegmail.com","password":"$2b$12$ULJ9tL7jh8yPXNDmCJi4C.mzkxzLfIQXakq3td9dJQs3io/Zg/AE2"}
|
||||
{"_id":{"$oid":"59b99e07cfa9a34dcd788668"},"name":"Jordan Medina","email":"jordan_medina@fakegmail.com","password":"$2b$12$QcSxfXU.jBizvmaU/zc33eIChz4lVAcQalzCupFBv3eGYEsVhJazW"}
|
||||
{"_id":{"$oid":"59b99e08cfa9a34dcd788669"},"name":"Donna Smith","email":"donna_smith@fakegmail.com","password":"$2b$12$LYIyq5Bsszh3/8efEYmJRuWDqhOeg8K5czQwSLxEBhOTyhOX34JEy"}
|
||||
{"_id":{"$oid":"59b99e08cfa9a34dcd78866a"},"name":"Shawn Mccormick","email":"shawn_mccormick@fakegmail.com","password":"$2b$12$fVJEFj7SXlqT0EmE9k00FuZLNH52NFSPriUqm8GGT6QQmuzrsMwUC"}
|
||||
{"_id":{"$oid":"59b99e09cfa9a34dcd78866b"},"name":"Anthony Hurst","email":"anthony_hurst@fakegmail.com","password":"$2b$12$9M2cew6pOM.35LY474rMkeVD4WxfvF2lDtVg60jZrlMdbaexrIfwK"}
|
||||
{"_id":{"$oid":"59b99e09cfa9a34dcd78866c"},"name":"Ashlee Hart","email":"ashlee_hart@fakegmail.com","password":"$2b$12$S707opDk6HG/Lqk7MaHeQ.1N36I6kEUOhRv/RQEHZUbw89xAuO6Ju"}
|
||||
{"_id":{"$oid":"5db1c37e4a68c31f10cf0a98"},"name":"Magical Mr. Mistoffelees","email":"magicz@cats.com","password":"somehashedpw"}
|
||||
{"_id":{"$oid":"5db1c37e4a68c31f10cf0a9f"},"name":"foo","email":"foobaz@bar.com","password":"foobar","preferences":{}}
|
0
rfcs/nosql-schema-sampling/schema_exports/.gitkeep
Normal file
0
rfcs/nosql-schema-sampling/schema_exports/.gitkeep
Normal file
46
rfcs/nosql-schema-sampling/schema_sampler/analyze.sh
Executable file
46
rfcs/nosql-schema-sampling/schema_sampler/analyze.sh
Executable file
@ -0,0 +1,46 @@
|
||||
#!/bin/bash
|
||||
echo "📥 Getting `mongosh` dependancies..."
|
||||
apt-get install -s -y gnupg
|
||||
wget -qO - https://www.mongodb.org/static/pgp/server-6.0.asc | apt-key add -
|
||||
echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/6.0 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-6.0.list
|
||||
apt-get update && apt-get -s upgrade
|
||||
apt-get install -y mongodb-mongosh
|
||||
|
||||
echo "🕵️♀️ Inspecting Collections..."
|
||||
# Collections to analyze
|
||||
if [[ -z "${MONGO_SELECT_COLLECTIONS}" ]]; then
|
||||
# Get all collections
|
||||
collections=$(mongosh --quiet --username ${MONGO_USERNAME} --password ${MONGO_PASSWORD} --authenticationDatabase=admin --eval "db.getCollectionNames()" ${MONGO_DATABASE} | tr -d '[\[\]"\ \n]')
|
||||
else
|
||||
# Only collections in env vars
|
||||
collections=${MONGO_SELECT_COLLECTIONS}
|
||||
fi
|
||||
IFS=',' read -ra COLLECTIONS <<< "$collections"
|
||||
|
||||
echo "📚 Collections for analysis: ${COLLECTIONS[@]}"
|
||||
echo '---------------------------------'
|
||||
|
||||
# Query each collection and run through variety
|
||||
mkdir -p /schema_exports/analysis
|
||||
for collection in "${COLLECTIONS[@]}"; do
|
||||
echo "🔍 Analyzing ${collection}..."
|
||||
# Run variety on the collection
|
||||
# Update this --eval query to match your needs (example, filter or limit how many records to analyze)
|
||||
mongosh ${MONGO_DATABASE} --quiet --eval "var collection = '${collection//\'/}', outputFormat='json'" --username ${MONGO_USERNAME} --password ${MONGO_PASSWORD} --authenticationDatabase=admin /schema_sampler/variety.js > "/schema_exports/analysis/${collection//\'/}.json"
|
||||
echo "✅ ${collection} analysis complete..."
|
||||
echo "💿 Converting analysis to validation schema..."
|
||||
|
||||
# Convert the variety output to a validation jsonschema
|
||||
node /schema_sampler/validation_exporter.js ${collection//\'/}
|
||||
echo "✅ ${collection} validation schema created..."
|
||||
|
||||
# Plug the json schema back into MongoDB if the user has selected that option
|
||||
if [[ "${MONGO_UPDATE_COLLECTIONS}" == "true" ]]; then
|
||||
echo "🔄 Updating ${collection} with validation schema in MongoDB..."
|
||||
schema=$(cat /schema_exports/validation_schema/${collection//\'/}.json)
|
||||
mongosh ${MONGO_DATABASE} --quiet --eval "db.runCommand({ collMod: '${collection//\'/}', validator: ${schema}, validationAction: 'warn' })" --username ${MONGO_USERNAME} --password ${MONGO_PASSWORD} --authenticationDatabase=admin
|
||||
echo "✅ ${collection} validation schema updated in MongoDB..."
|
||||
fi
|
||||
echo '---------------------------------'
|
||||
done
|
||||
echo "✅ Collection analysis and update complete..."
|
55
rfcs/nosql-schema-sampling/schema_sampler/validation_exporter.js
Executable file
55
rfcs/nosql-schema-sampling/schema_sampler/validation_exporter.js
Executable file
@ -0,0 +1,55 @@
|
||||
const fs = require("fs");
|
||||
let collection = process.argv[2];
|
||||
|
||||
let rawdata = fs.readFileSync(`/schema_exports/analysis/${collection}.json`);
|
||||
let analysisData = JSON.parse(rawdata);
|
||||
let schema = {
|
||||
$jsonSchema: {
|
||||
bsonType: "object",
|
||||
required: [""],
|
||||
properties: {},
|
||||
},
|
||||
};
|
||||
let output = {};
|
||||
const createTemplate = (obj) => {
|
||||
obj.forEach((element) => {
|
||||
const keys = element._id.key.split(".");
|
||||
const typeKeys = Object.keys(element.value.types);
|
||||
let type;
|
||||
if (typeKeys.length > 1) {
|
||||
type = "string";
|
||||
} else {
|
||||
type = typeKeys[0].toLowerCase();
|
||||
}
|
||||
const convertedType = type === "objectid" ? "objectId" : type;
|
||||
|
||||
let subObj = output;
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
if (!subObj.properties) {
|
||||
subObj.properties = {};
|
||||
}
|
||||
|
||||
if (!subObj.properties[keys[i]]) {
|
||||
if (i < keys.length - 1 || convertedType === "object") {
|
||||
subObj.properties[keys[i]] = {};
|
||||
} else {
|
||||
subObj.properties[keys[i]] = { bsonType: convertedType };
|
||||
}
|
||||
}
|
||||
|
||||
if (i === keys.length - 1 && convertedType === "object") {
|
||||
subObj.properties[keys[i]].bsonType = convertedType;
|
||||
subObj = subObj.properties[keys[i]];
|
||||
} else {
|
||||
subObj = subObj.properties[keys[i]];
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
createTemplate(analysisData);
|
||||
schema.$jsonSchema = output;
|
||||
fs.writeFileSync(
|
||||
`/schema_exports/validation_schema/${collection}.json`,
|
||||
JSON.stringify(schema, null, 2)
|
||||
);
|
421
rfcs/nosql-schema-sampling/schema_sampler/variety.js
Normal file
421
rfcs/nosql-schema-sampling/schema_sampler/variety.js
Normal file
@ -0,0 +1,421 @@
|
||||
/* Variety: A MongoDB Schema Analyzer
|
||||
|
||||
This tool helps you get a sense of your application's schema, as well as any
|
||||
outliers to that schema. Particularly useful when you inherit a codebase with
|
||||
data dump and want to quickly learn how the data's structured. Also useful for
|
||||
finding rare keys.
|
||||
|
||||
Please see https://github.com/variety/variety for details.
|
||||
|
||||
Released by Maypop Inc, © 2012–2023, under the MIT License. */
|
||||
|
||||
(function () {
|
||||
'use strict'; // wraps everything for which we can use strict mode -JC
|
||||
|
||||
var log = function(message) {
|
||||
// print(message);
|
||||
};
|
||||
|
||||
log('Variety: A MongoDB Schema Analyzer');
|
||||
log('Version 1.5.1, released 02 October 2017');
|
||||
|
||||
var dbs = [];
|
||||
var emptyDbs = [];
|
||||
|
||||
if (typeof slaveOk !== 'undefined') {
|
||||
if (slaveOk === true) {
|
||||
db.getMongo().setSlaveOk();
|
||||
}
|
||||
}
|
||||
|
||||
var knownDatabases = db.adminCommand('listDatabases').databases;
|
||||
if(typeof knownDatabases !== 'undefined') { // not authorized user receives error response (json) without databases key
|
||||
knownDatabases.forEach(function(d){
|
||||
if(db.getSiblingDB(d.name).getCollectionNames().length > 0) {
|
||||
dbs.push(d.name);
|
||||
}
|
||||
if(db.getSiblingDB(d.name).getCollectionNames().length === 0) {
|
||||
emptyDbs.push(d.name);
|
||||
}
|
||||
});
|
||||
|
||||
if (emptyDbs.indexOf(db.getName()) !== -1) {
|
||||
throw 'The database specified ('+ db +') is empty.\n'+
|
||||
'Possible database options are: ' + dbs.join(', ') + '.';
|
||||
}
|
||||
|
||||
if (dbs.indexOf(db.getName()) === -1) {
|
||||
throw 'The database specified ('+ db +') does not exist.\n'+
|
||||
'Possible database options are: ' + dbs.join(', ') + '.';
|
||||
}
|
||||
}
|
||||
|
||||
var collNames = db.getCollectionNames().join(', ');
|
||||
if (typeof collection === 'undefined') {
|
||||
throw 'You have to supply a \'collection\' variable, à la --eval \'var collection = "animals"\'.\n'+
|
||||
'Possible collection options for database specified: ' + collNames + '.\n'+
|
||||
'Please see https://github.com/variety/variety for details.';
|
||||
}
|
||||
|
||||
if (db.getCollection(collection).countDocuments({}, {limit: 1}) === 0) {
|
||||
throw 'The collection specified (' + collection + ') in the database specified ('+ db +') does not exist or is empty.\n'+
|
||||
'Possible collection options for database specified: ' + collNames + '.';
|
||||
}
|
||||
|
||||
var readConfig = function(configProvider) {
|
||||
var config = {};
|
||||
var read = function(name, defaultValue) {
|
||||
var value = typeof configProvider[name] !== 'undefined' ? configProvider[name] : defaultValue;
|
||||
config[name] = value;
|
||||
log('Using '+name+' of ' + JSON.stringify(value));
|
||||
};
|
||||
read('collection', null);
|
||||
read('query', {});
|
||||
read('limit', db.getCollection(config.collection).find(config.query).count());
|
||||
read('maxDepth', 99);
|
||||
read('sort', {_id: -1});
|
||||
read('outputFormat', 'ascii');
|
||||
read('persistResults', false);
|
||||
read('resultsDatabase', 'varietyResults');
|
||||
read('resultsCollection', collection + 'Keys');
|
||||
read('resultsUser', null);
|
||||
read('resultsPass', null);
|
||||
read('logKeysContinuously', false);
|
||||
read('excludeSubkeys', []);
|
||||
read('arrayEscape', 'XX');
|
||||
read('lastValue', false);
|
||||
|
||||
//Translate excludeSubkeys to set like object... using an object for compatibility...
|
||||
config.excludeSubkeys = config.excludeSubkeys.reduce(function (result, item) { result[item+'.'] = true; return result; }, {});
|
||||
|
||||
return config;
|
||||
};
|
||||
|
||||
var config = readConfig(this);
|
||||
|
||||
var PluginsClass = function(context) {
|
||||
var parsePath = function(val) { return val.slice(-3) !== '.js' ? val + '.js' : val;};
|
||||
var parseConfig = function(val) {
|
||||
var config = {};
|
||||
val.split('&').reduce(function(acc, val) {
|
||||
var parts = val.split('=');
|
||||
acc[parts[0]] = parts[1];
|
||||
return acc;
|
||||
}, config);
|
||||
return config;
|
||||
};
|
||||
|
||||
if(typeof context.plugins !== 'undefined') {
|
||||
this.plugins = context.plugins.split(',')
|
||||
.map(function(path){return path.trim();})
|
||||
.map(function(definition){
|
||||
var path = parsePath(definition.split('|')[0]);
|
||||
var config = parseConfig(definition.split('|')[1] || '');
|
||||
context.module = context.module || {};
|
||||
load(path);
|
||||
var plugin = context.module.exports;
|
||||
plugin.path = path;
|
||||
if(typeof plugin.init === 'function') {
|
||||
plugin.init(config);
|
||||
}
|
||||
return plugin;
|
||||
}, this);
|
||||
} else {
|
||||
this.plugins = [];
|
||||
}
|
||||
|
||||
this.execute = function(methodName) {
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
var applicablePlugins = this.plugins.filter(function(plugin){return typeof plugin[methodName] === 'function';});
|
||||
return applicablePlugins.map(function(plugin) {
|
||||
return plugin[methodName].apply(plugin, args);
|
||||
});
|
||||
};
|
||||
|
||||
log('Using plugins of ' + JSON.stringify(this.plugins.map(p => p.path)));
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
var $plugins = new PluginsClass(this);
|
||||
$plugins.execute('onConfig', config);
|
||||
|
||||
var varietyTypeOf = function(thing) {
|
||||
if (!arguments.length) { throw 'varietyTypeOf() requires an argument'; }
|
||||
|
||||
if (typeof thing === 'undefined') {
|
||||
return 'undefined';
|
||||
} else if (typeof thing !== 'object') {
|
||||
// the messiness below capitalizes the first letter, so the output matches
|
||||
// the other return values below. -JC
|
||||
var typeofThing = typeof thing; // edgecase of JSHint's "singleGroups"
|
||||
return typeofThing[0].toUpperCase() + typeofThing.slice(1);
|
||||
} else {
|
||||
if (thing && thing.constructor === Array) {
|
||||
return 'Array';
|
||||
} else if (thing === null) {
|
||||
return 'null';
|
||||
} else if (thing instanceof Date) {
|
||||
return 'Date';
|
||||
} else if(thing instanceof NumberLong) {
|
||||
return 'NumberLong';
|
||||
} else if (thing instanceof ObjectId) {
|
||||
return 'ObjectId';
|
||||
} else if (thing instanceof BinData) {
|
||||
var binDataTypes = {};
|
||||
binDataTypes[0x00] = 'generic';
|
||||
binDataTypes[0x01] = 'function';
|
||||
binDataTypes[0x02] = 'old';
|
||||
binDataTypes[0x03] = 'UUID';
|
||||
binDataTypes[0x04] = 'UUID';
|
||||
binDataTypes[0x05] = 'MD5';
|
||||
binDataTypes[0x80] = 'user';
|
||||
return 'BinData-' + binDataTypes[thing.subtype()];
|
||||
} else {
|
||||
return 'Object';
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//flattens object keys to 1D. i.e. {'key1':1,{'key2':{'key3':2}}} becomes {'key1':1,'key2.key3':2}
|
||||
//we assume no '.' characters in the keys, which is an OK assumption for MongoDB
|
||||
var serializeDoc = function(doc, maxDepth, excludeSubkeys) {
|
||||
var result = {};
|
||||
|
||||
//determining if an object is a Hash vs Array vs something else is hard
|
||||
//returns true, if object in argument may have nested objects and makes sense to analyse its content
|
||||
function isHash(v) {
|
||||
var isArray = Array.isArray(v);
|
||||
var isObject = typeof v === 'object';
|
||||
var specialObject = v instanceof Date ||
|
||||
v instanceof ObjectId ||
|
||||
v instanceof BinData ||
|
||||
v instanceof NumberLong;
|
||||
return !specialObject && (isArray || isObject);
|
||||
}
|
||||
|
||||
var arrayRegex = new RegExp('\\.' + config.arrayEscape + '\\d+' + config.arrayEscape + '\\.', 'g');
|
||||
|
||||
function serialize(document, parentKey, maxDepth) {
|
||||
if(Object.prototype.hasOwnProperty.call(excludeSubkeys, parentKey.replace(arrayRegex, '.')))
|
||||
return;
|
||||
for(var key in document) {
|
||||
//skip over inherited properties such as string, length, etch
|
||||
if(!document.hasOwnProperty(key)) {
|
||||
continue;
|
||||
}
|
||||
var value = document[key];
|
||||
if(Array.isArray(document))
|
||||
key = config.arrayEscape + key + config.arrayEscape; //translate unnamed object key from {_parent_name_}.{_index_} to {_parent_name_}.arrayEscape{_index_}arrayEscape.
|
||||
result[parentKey+key] = value;
|
||||
//it's an object, recurse...only if we haven't reached max depth
|
||||
if(isHash(value) && maxDepth > 1) {
|
||||
serialize(value, parentKey+key+'.', maxDepth-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
serialize(doc, '', maxDepth);
|
||||
return result;
|
||||
};
|
||||
|
||||
// convert document to key-value map, where value is always an array with types as plain strings
|
||||
var analyseDocument = function(document) {
|
||||
var result = {};
|
||||
var arrayRegex = new RegExp('\\.' + config.arrayEscape + '\\d+' + config.arrayEscape, 'g');
|
||||
for (var key in document) {
|
||||
var value = document[key];
|
||||
key = key.replace(arrayRegex, '.' + config.arrayEscape);
|
||||
if(typeof result[key] === 'undefined') {
|
||||
result[key] = {};
|
||||
}
|
||||
var type = varietyTypeOf(value);
|
||||
result[key][type] = null;
|
||||
|
||||
if(config.lastValue){
|
||||
if (type in {'String': true, 'Boolean': true}) {
|
||||
result[key][type] = value.toString();
|
||||
}else if (type in {'Number': true, 'NumberLong': true}) {
|
||||
result[key][type] = value.valueOf();
|
||||
}else if(type == 'ObjectId'){
|
||||
result[key][type] = value.str;
|
||||
}else if(type == 'Date'){
|
||||
result[key][type] = new Date(value).getTime();
|
||||
}else if(type.startsWith('BinData')){
|
||||
result[key][type] = value.hex();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
var mergeDocument = function(docResult, interimResults) {
|
||||
for (var key in docResult) {
|
||||
if(key in interimResults) {
|
||||
var existing = interimResults[key];
|
||||
|
||||
for(var type in docResult[key]) {
|
||||
if (type in existing.types) {
|
||||
existing.types[type] = existing.types[type] + 1;
|
||||
} else {
|
||||
existing.types[type] = 1;
|
||||
if (config.logKeysContinuously) {
|
||||
log('Found new key type "' + key + '" type "' + type + '"');
|
||||
}
|
||||
}
|
||||
}
|
||||
existing.totalOccurrences = existing.totalOccurrences + 1;
|
||||
} else {
|
||||
var lastValue = null;
|
||||
var types = {};
|
||||
for (var newType in docResult[key]) {
|
||||
types[newType] = 1;
|
||||
lastValue = docResult[key][newType];
|
||||
if (config.logKeysContinuously) {
|
||||
log('Found new key type "' + key + '" type "' + newType + '"');
|
||||
}
|
||||
}
|
||||
interimResults[key] = {'types': types,'totalOccurrences':1};
|
||||
if (config.lastValue) {
|
||||
interimResults[key]['lastValue'] = lastValue ? lastValue : '['+newType+']';
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var convertResults = function(interimResults, documentsCount) {
|
||||
var getKeys = function(obj) {
|
||||
var keys = {};
|
||||
for(var key in obj) {
|
||||
keys[key] = obj[key];
|
||||
}
|
||||
return keys;
|
||||
//return keys.sort();
|
||||
};
|
||||
var varietyResults = [];
|
||||
//now convert the interimResults into the proper format
|
||||
for(var key in interimResults) {
|
||||
var entry = interimResults[key];
|
||||
|
||||
var obj = {
|
||||
'_id': {'key':key},
|
||||
'value': {'types':getKeys(entry.types)},
|
||||
'totalOccurrences': entry.totalOccurrences,
|
||||
'percentContaining': entry.totalOccurrences * 100 / documentsCount
|
||||
};
|
||||
|
||||
if(config.lastValue){
|
||||
obj.lastValue = entry.lastValue;
|
||||
}
|
||||
|
||||
varietyResults.push(obj);
|
||||
}
|
||||
return varietyResults;
|
||||
};
|
||||
|
||||
// Merge the keys and types of current object into accumulator object
|
||||
var reduceDocuments = function(accumulator, object) {
|
||||
var docResult = analyseDocument(serializeDoc(object, config.maxDepth, config.excludeSubkeys));
|
||||
mergeDocument(docResult, accumulator);
|
||||
return accumulator;
|
||||
};
|
||||
|
||||
// We throw away keys which end in an array index, since they are not useful
|
||||
// for our analysis. (We still keep the key of their parent array, though.) -JC
|
||||
var arrayRegex = new RegExp('\\.' + config.arrayEscape + '$', 'g');
|
||||
var filter = function(item) {
|
||||
return !item._id.key.match(arrayRegex);
|
||||
};
|
||||
|
||||
// sort desc by totalOccurrences or by key asc if occurrences equal
|
||||
var comparator = function(a, b) {
|
||||
var countsDiff = b.totalOccurrences - a.totalOccurrences;
|
||||
return countsDiff !== 0 ? countsDiff : a._id.key.localeCompare(b._id.key);
|
||||
};
|
||||
|
||||
var cursor = db.getCollection(config.collection).find(config.query).sort(config.sort).limit(config.limit);
|
||||
|
||||
var interimResults = {};
|
||||
cursor.forEach(function(obj){
|
||||
interimResults = reduceDocuments(interimResults, obj);
|
||||
});
|
||||
|
||||
var varietyResults = convertResults(interimResults, cursor.size())
|
||||
.filter(filter)
|
||||
.sort(comparator);
|
||||
|
||||
if(config.persistResults) {
|
||||
var resultsDB;
|
||||
var resultsCollectionName = config.resultsCollection;
|
||||
|
||||
if (config.resultsDatabase.indexOf('/') === -1) {
|
||||
// Local database; don't reconnect
|
||||
resultsDB = db.getMongo().getDB(config.resultsDatabase);
|
||||
} else {
|
||||
// Remote database, establish new connection
|
||||
resultsDB = connect(config.resultsDatabase);
|
||||
}
|
||||
|
||||
if (config.resultsUser !== null && config.resultsPass !== null) {
|
||||
resultsDB.auth(config.resultsUser, config.resultsPass);
|
||||
}
|
||||
|
||||
// replace results collection
|
||||
log('replacing results collection: '+ resultsCollectionName);
|
||||
resultsDB.getCollection(resultsCollectionName).drop();
|
||||
resultsDB.getCollection(resultsCollectionName).insert(varietyResults);
|
||||
}
|
||||
|
||||
var createAsciiTable = function(results) {
|
||||
var headers = ['key', 'types', 'occurrences', 'percents'];
|
||||
if (config.lastValue) {
|
||||
headers.push('lastValue');
|
||||
}
|
||||
|
||||
// return the number of decimal places or 1, if the number is int (1.23=>2, 100=>1, 0.1415=>4)
|
||||
var significantDigits = function(value) {
|
||||
var res = value.toString().match(/^[0-9]+\.([0-9]+)$/);
|
||||
return res !== null ? res[1].length : 1;
|
||||
};
|
||||
|
||||
var maxDigits = varietyResults.map(function(value){return significantDigits(value.percentContaining);}).reduce(function(acc,val){return acc>val?acc:val;});
|
||||
|
||||
var rows = results.map(function(row) {
|
||||
var types = [];
|
||||
var typeKeys = Object.keys(row.value.types);
|
||||
if (typeKeys.length > 1) {
|
||||
for (var type in row.value.types) {
|
||||
var typestring = type + ' (' + row.value.types[type] + ')';
|
||||
types.push(typestring);
|
||||
}
|
||||
} else {
|
||||
types = typeKeys;
|
||||
}
|
||||
|
||||
var rawArray = [row._id.key, types, row.totalOccurrences, row.percentContaining.toFixed(Math.min(maxDigits, 20))];
|
||||
if (config.lastValue && row['lastValue']) {
|
||||
rawArray.push(row['lastValue']);
|
||||
}
|
||||
return rawArray;
|
||||
});
|
||||
var table = [headers, headers.map(function(){return '';})].concat(rows);
|
||||
var colMaxWidth = function(arr, index) {return Math.max.apply(null, arr.map(function(row){return row[index] ? row[index].toString().length : 0;}));};
|
||||
var pad = function(width, string, symbol) { return width <= string.length ? string : pad(width, isNaN(string) ? string + symbol : symbol + string, symbol); };
|
||||
table = table.map(function(row, ri){
|
||||
return '| ' + row.map(function(cell, i) {return pad(colMaxWidth(table, i), cell.toString(), ri === 1 ? '-' : ' ');}).join(' | ') + ' |';
|
||||
});
|
||||
var border = '+' + pad(table[0].length - 2, '', '-') + '+';
|
||||
return [border].concat(table).concat(border).join('\n');
|
||||
};
|
||||
|
||||
var pluginsOutput = $plugins.execute('formatResults', varietyResults);
|
||||
if (pluginsOutput.length > 0) {
|
||||
pluginsOutput.forEach(function(i){print(i);});
|
||||
} else if(config.outputFormat === 'json') {
|
||||
printjson(JSON.stringify(varietyResults));
|
||||
// printjson(varietyResults); // valid formatted json output, compressed variant is printjsononeline()
|
||||
} else {
|
||||
print(createAsciiTable(varietyResults)); // output nice ascii table with results
|
||||
}
|
||||
|
||||
}.bind(this)()); // end strict mode
|
Loading…
Reference in New Issue
Block a user