Skip to content

Add unique fields only capability to schema.  #6059

Open

Description

@noobs2ninjas

It would be really great if we could add like a uniqueFieldsOnly parameter to the schema rest functionality.

Recently I've been working in a more professional/complex deployment pipeline where I have a Production, Development, and local parse servers. This brought me to the schema endpoint for deploying structure changes down the pipeline. As you know doing a POST to the schema endpoint with anything that is reserved internally such as objectId, updatedAt, createdAt will return you an error making it impossible to simply take the data returned from a schema request on one parse instance and posting it to another. I was about to write a script to save me from removing these fields by hand and figured it may be worth discussing adding this feature to the server itself as I'm sure others deal with similar scenarios.

Activity

  1. davimacedo commented on Sep 17, 2019

    @davimacedo
    Member

    Can you detail how the uniqueFieldsOnly option would work?

  2. noobs2ninjas commented on Sep 17, 2019

    @noobs2ninjas
    MemberAuthor

    The option would simply ignore all universal system reserved fields(objectId, createdAt, updatedAt) as well as any additional system info. So, rather than returning this.

    {
      "results": [
        {
          "className": "Game",
          "fields": {
            "ACL": {
              "type": "ACL"
            },
            "createdAt": {
              "type": "Date"
            },
            "objectId": {
              "type": "String"
            },
            "name": {
              "type": "String"
            },
            "score": {
              "type": "Number"
            },
            "updatedAt": {
              "type": "Date"
            }
          }
        },
        "classLevelPermissions": {
                    "find": {
                        "*": true
                    },
                    "count": {
                        "*": true
                    },
                    "get": {
                        "*": true
                    },
                    "create": {
                        "*": true
                    },
                    "update": {
                        "*": true
                    },
                    "delete": {
                        "*": true
                    },
                    "addField": {
                        "*": true
                    },
                    "protectedFields": {
                        "*": []
                    }
                },
        "indexes": {
            "_id_": {
                "_id": 1
            }
        }
      ]
    }
    

    It would return this.

    {
      "results": [
        {
          "className": "Game",
          "fields": {
            "name": {
              "type": "String"
            },
            "score": {
              "type": "Number"
            }
          }
        }
      ]
    }
    

    In other words it would return just the data thats allowed when doing a POST or PUT to the schema endpoint. Making things like automated schema deployment, transfering, or duplication much much simpler because you can use the data returned pretty much as-is.

  3. davimacedo commented on Sep 17, 2019

    @davimacedo
    Member

    I think your issue is related to this one. But I am afraid that, even returning these fields, you will not be able to just push them to the schema API since Parse Server does not currently support changing existing fields. I think we should come up not only with an option in the existing API, but two new endpoints (pullSchema and pushSchema) that are specially designed for schema control and migration. Maybe we should also add two commands to the CLI as well. What do you think? @dplewis @acinader thoughts?

  4. noobs2ninjas commented on Sep 17, 2019

    @noobs2ninjas
    MemberAuthor

    That would add such great potential that goes way beyond even what I was hoping for.

    You know whats funny is that I think what you just suggested was the entire goal of schema when it was released. It's been a while but I remember an article on the parse homepage, we're talking even before Facebook bought Parse when schema was first announced that talked about a long term goal of wanting to appeal to SAAS and PAAS developers.

    I think it goes beyond that though and would make it easy to take Parse in the direction the rest of the industry is already going. More and more companies are using things like docker and kubernetes(same thing?) to do things like scale and deploy database instances rather than relying on massive database servers. pull and push schema would be a huge steps in writing easy scripts that do just that. If anyone has rails experience this could aid in writing automated rake-like migration scripts. Some day it may even be able to help us add the one feature everyones asked for since Parse went open source. An import/export database button on Dashboard.

    Sorry to drone on. By the way the main thing that has me asking here is because the Javascript SDK doesnt allow you to initialize a schema with a string period which is why I had to revert to using the rest endpoints. You think I should go suggest that over there? Let me know if you'd like any help. I work on the Parse iOS sdk and know my away around parse-server a fair bit.

  5. davimacedo commented on Sep 19, 2019

    @davimacedo
    Member

    Nice! I think we should go for it. Its this something that you would be willed to tackle?

    I didn't understand the issue with the JS SDK, but I think it would be good you open the issue in its repo.

  6. noobs2ninjas commented on Sep 19, 2019

    @noobs2ninjas
    MemberAuthor

    In the Javascript SDK you can actually do lots of stuff to modify a schema. mySchema.addString('stringField') etc...

    However, there is no functionality to retrieve or initialize a classes schema data within the JS SDK. In other words there is no const mySchema = new Parse.Schema(schemaData) or const schemaData = mySchema.getData(). Had there been I probably wouldn't have looked to post an issue here as I could have easily scripted the whole thing.

  7. davimacedo commented on Sep 20, 2019

    @davimacedo
    Member

    got it... I see that const schemaData = mySchema.getData() could be easily added, but const mySchema = new Parse.Schema(schemaData) would not be useful because there is no API to do mySchema.save() later as Parse Server does not allow to modify existing fields.

  8. noobs2ninjas commented on Sep 20, 2019

    @noobs2ninjas
    MemberAuthor

    You could save if the schema being created was a new class for that server and not a new instance. Which is what I was needing. Taking a class from one server and creating/duplicating it on another server.

  9. davimacedo commented on Sep 27, 2019

    @davimacedo
    Member

    For this case, wouldn't be better you call schema.save() individually for each new class you want to save? Or maybe Parse.Schema.create(listOfClassesToCreate) ?

  10. noobs2ninjas commented on Sep 28, 2019

    @noobs2ninjas
    MemberAuthor

    I was suggesting this because I think it would be easy. currently the Schema class on the JS SDK has the following.

    constructor(className: string) {
        if (typeof className === 'string') {
          if (className === 'User' && CoreManager.get('PERFORM_USER_REWRITE')) {
            this.className = '_User';
          } else {
            this.className = className;
          }
        }
    
        this._fields = {};
        this._indexes = {};
    }
    

    Now I know you cant have two constructors but you could create a static function that basically accomplishes the following

    constructor(schemaData) {
        this.className = schemaData.className;
    
        this._fields = schemaData.fields;
        this._indexes = {};
    }
    

    Something super simple that you can hit up https://YOUR.PARSE-SERVER.HERE/parse/schemas/myClass and with the userFieldsOnly feature which removes the createdAt etcc... so you can just take the response as-is and do the following.

    let newSchema = Parse.Schema.schemaWithData(schemaData);
    newSchema.save();
    

    I do want to do multi class initializations. Unless I'm missing something though, single class creation from schema data should be pretty easy to do. What would also be pretty exiting about that is you could simply have a JSON file with an array of your class schemas. Then, when you kick off a new parse server environment, read that file, and loop and create all your classes with only a few lines of code and very little effort. Fast simple server duplication.

  11. davimacedo commented on Oct 2, 2019

    @davimacedo
    Member

    Do you like to send a PR with this idea so we can better discuss?

  12. femolacaster commented on Sep 8, 2021

    @femolacaster

    😊 I think this is an issue I would love to tackle as I am trying to get my hands around Parse. Maybe I should add a PR down already.

  13. mtrezza commented on Sep 10, 2021

    @mtrezza
    Member

    @femolacaster That's great to hear! See our Contribution Guide for how to make a pull request, or read our New Contributor's Guide if this is your first time contributing.

    Mind that @fn-faisal already opened #7388, which may already address this issue. You could just look over the PR and the changes to see how far it is and whether you have any suggestions for improvement.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    type:featureNew feature or improvement of existing feature

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions