parse-community / parse-server

Parse Server for Node.js / Express
https://parseplatform.org
Apache License 2.0
20.85k stars 4.78k forks source link

Add unique fields only capability to schema. #6059

Open noobs2ninjas opened 5 years ago

noobs2ninjas commented 5 years ago

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 commented 5 years ago

Can you detail how the uniqueFieldsOnly option would work?

noobs2ninjas commented 5 years ago

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 commented 5 years ago

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 commented 5 years ago

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 commented 5 years ago

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 commented 5 years ago

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 commented 5 years ago

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 commented 5 years ago

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 commented 5 years ago

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 commented 5 years ago

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 commented 4 years ago

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

femolacaster commented 3 years ago

😊 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 commented 3 years ago

@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 https://github.com/parse-community/parse-server/pull/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.