Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add unique fields only capability to schema. #6059

Open
noobs2ninjas opened this issue Sep 17, 2019 · 13 comments
Open

Add unique fields only capability to schema. #6059

noobs2ninjas opened this issue Sep 17, 2019 · 13 comments
Labels
type:feature New feature or improvement of existing feature

Comments

@noobs2ninjas
Copy link
Member

noobs2ninjas commented Sep 17, 2019

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.

@davimacedo davimacedo added type:feature New feature or improvement of existing feature discussion labels Sep 17, 2019
@davimacedo
Copy link
Member

Can you detail how the uniqueFieldsOnly option would work?

@noobs2ninjas
Copy link
Member Author

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.

@davimacedo
Copy link
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?

@noobs2ninjas
Copy link
Member Author

noobs2ninjas commented Sep 17, 2019

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.

@davimacedo
Copy link
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.

@noobs2ninjas
Copy link
Member Author

noobs2ninjas commented Sep 19, 2019

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.

@davimacedo
Copy link
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.

@noobs2ninjas
Copy link
Member Author

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.

@davimacedo
Copy link
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) ?

@noobs2ninjas
Copy link
Member Author

noobs2ninjas commented Sep 28, 2019

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.

@davimacedo
Copy link
Member

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

@femolacaster
Copy link

😊 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.

@mtrezza
Copy link
Member

mtrezza commented Sep 10, 2021

@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
Labels
type:feature New feature or improvement of existing feature
Projects
None yet
Development

No branches or pull requests

4 participants