Navigation

MongoDB Service Write Rule

Write Rule

MongoDB Stitch applies the MongoDB Service write rules to determine whether a write operation is permissible. The client can modify those fields for which the write rule evaluates to true.

Important

Query predicates do not match any documents if the predicates include fields that are unreadable as determined by the read rules. See MongoDB Service Read Rule for more information on read rules.

MongoDB Authorization

MongoDB Stitch rules do not override the read and write access (i.e. authorization) that may have been set up separately in MongoDB. That is, MongoDB Stitch rules determine whether the fields are readable or writable; not whether the client has authorization to read or write to a particular database or collection.

Stop on Error Behavior

If a write operation modifies multiple documents and one of the document violates the write rules, the write operation stops upon error and does not continue processing any remaining documents.

This can occur if you add write rules to an existing collection with documents that may violate the new write rules.

To modify existing fields that violate new write rules, such as to delete documents that contain these fields or to $unset these fields, you can add each of these fields with a write rule {"%%this": {"%exists": false}}.

Default Write Rules

To view the write rule, click on the Top-Level Document in the Field Rules view.

By default, the collection has the following write rule for the top-level document:

{
  "owner_id": "%%user.id"
}

With this rule, the write operation must result in a document where the owner_id equals the user ID of the client issuing the write. If the value of owner_id does not match the client user ID, MongoDB Stitch blocks the write.

Rules Syntax

You can specify rules as JSON documents. MongoDB query expression operators (with the exception of the %text and the geospatial operators) are available for rule expressions.

{
  <field1>: <value1|expression1>,
  <field2>: <value2|expression2>,
  ...
}

To access elements of an array or access fields in an embedded document, use dot notation. For list of MongoDB query operators available, see Query Selectors.

You can also preface the <field> name with an expansion (%%<keyword>):

{
  "<expansion>.<field1>":  <value1|expression1>,
  "<expansion>.<field2>":  <value2|expression2>,
  ...
}

Tip

  • When a field is referenced at the top-level of a document rule, a field name <field> without any expansion is shorthand for %%root.<field>. In a write rule, %%root refers to the document after the write operation.

    However , if a compound rule includes nested expressions, you must explictly include the expansion for a field in the nested expressions.

  • When specifying a rule at a field level, you can use %%this to refer to the field; e.g., { "%%this": <value> }.

    • In a write rule for a document, %%this refers to the document after the write operation.
    • In a write rule for a field, %%this refers to the field after the write operation.

The following table lists some syntax examples:

Syntax Examples Description
{} An empty JSON document evaluates to true. If specified as a document rule, all documents satisfy this write rule. If specified as a field rule, the field is always writeable.
{ "%%true": true } The expression always evaluates to true as the value of the expansion %%true equals the boolean true. If specified as a document rule, all documents satisfy this write rule. If specified as a field rule, the field is always writeable.
{ "%%true": false } The expression always evaluates to false as the reserved expansion value %%true does not equal the boolean false. If specified as a document rule, no document satisfies this write rule. If specified as a field rule, the field is never writeable.
{
  "<field1>": <value1|exp1>,
  "<field2>": <value2|exp2>,
  ...
}

or

{
   "<expansion1>.<field1>": <value1|exp1>,
   "<expansion2>.<field2>": <value2|exp2>,
   ...
}
The compound document/field rule evaluates to true if all conditions are satisfied.
{
  "%or": [
     { "<expansion>.<field1>": <value1|exp1> },
     { "<expansion>.<field2>": <value2|exp2> },
     ...
  ]
}

The compound document/field rule evaluates to true if any of the specified conditions is satisfied.

Note

You must include expansions %%<keyword> to reference fields in the nested rule expressions.

Write Rule Examples

Important

When applying rules, the rules at the highest level applies. For a rule for a field to take effect, no rules must exist at a higher level. For details, see Rules Interaction.

The examples below add write rules on an existing collection reports that already contains the following documents:

{
   "_id" : 1,
   "title" : "Pies",
   "about" : { "subject" : "pies", "counts" : { "pages" : 5, "words" : 100 } },
   "classification" : "Public",
   "views" : 100
}
{
   "_id" : 2,
   "title" : "Pastries Part 1",
   "about" : { "subject" : "puff pastries", "counts" : { "pages" : 50, "words" : 5000 } },
   "classification" : "Public",
   "views" : 20
}
{
  "_id" : 3,
  "title" : "Cakes",
  "about" : { "subject" : "cupcakes", "counts" : { "pages" : 1, "words" : 200 } },
  "classification" : "Internal",
  "views" : 50
 }

The following table describe the effects of the write rule when either the rule is specified for the document or the rule is specified for the field about.counts. The summary table is followed by specific examples.

Examples Description
{}

If the rule is specified for the document, any and all fields are writable for any document if Allow All Other Fields is enabled. Otherwise, only listed fields are writable. For specific examples, see All Fields Are Writable for Any Write Operation.

If the rule is specified for the field about.counts, the field and its embedded fields pages and words are writable for all documents. Other fields are determined by Allow All Other Fields setting. For this field rule to take effect, rules cannot exist at the document level or for the about field. You can specify a separate rule for the title field, about.subject field, and the type field.

For specific example, see Only Specific Embedded Fields Are Writable.

If specifying the rule at the document level

{
  "%or": [
   {"%%root.about.counts.words": {"%gt": 0}},
   {"%%prevRoot.about.counts.words": {"%gt": 0},
    "%%root.about.counts.words": {"%exists": false}}
  ]
}

- or -

If specifying the rule for the about.count field

{
   "%or": [
      { "%%this.words": { "%gt": 0 } },
      { "%%prev.words": { "%gt": 0 },
        "%%this.words": { "%exists": false } }
   ]
}

If the rule is specified for the document, fields are writable:

  • if the "about.count.words" field is greater than 0 after the write operation, or
  • if the field was greater than 0 before the write operation and no longer exists after the write operation.

The determination of which fields this document rule applies to depends on the Allow All Other Fields setting and listed fields.

If the rule is specified for the field about.counts, then the field and its embedded fields pages and words are writable if the "about.count.words" field is greater than 0 after the write operation (or prior to the write is greater than 0 and is deleted after the write operation). Other fields are determined by Allow All Other Fields setting. For this rule to take effect, rules cannot exist at the document level or for the about field. You can, however, specify a separate rule for the title field. For a specific example, see Specify Different Write Rules for Fields.

All Fields Are Writable for Any Write Operation

Note

Query predicates do not match any documents if the predicates include fields that are determined unreadable by the read rules. For simplicity, the following examples assume all fields are readable. See MongoDB Service Read Rule for more information on read rules.

This examples sets up MongoDB Stitch rules to ensure that all fields are available for insert, update, and delete operations.

To make all fields available for any write operations:

  • Specify an empty JSON document {} as the write rule at document level.
  • Set Allow All Other Fields to enabled.

Given these rule at the document level, all write operations are allowed. For example, the following StitchClient write operations are allowed:

db.getCollection("reports").insert(
   {
     "title": "Tarts",
     "classification": "Public",
     "views": 101,
     "about": { "subject": "pies", "counts": { "pages": 10, "words": 500 } }
    }
);
db.getCollection("reports").updateMany( { "classification":"Public" }, { "$inc": { "views": 1 } } );
db.getCollection("reports").deleteOne( { "classification":"Public" } );

All Listed Fields Are Writable for Documents Matching Rule Condition

Note

Query predicates do not match any documents if the predicates include fields that are determined unreadable by the read rules. For simplicity, the following examples assume all fields are readable. See MongoDB Service Read Rule for more information on read rules.

This examples sets up MongoDB Stitch rules to ensure that all fields are writable:

  • if the "about.count.words" field is greater than 0 after the write operation, or
  • if the field was greater than 0 and no longer exists after the write operation.

To make all fields available under these conditions:

  • Specify the following write rule for the document

    {
       "%or": [
          { "%%root.about.counts.words": { "%gt": 0 } },
          { "%%prevRoot.about.counts.words": { "%gt": 0 },
            "%%root.about.counts.words": { "%exists": false } }
       ]
    }
    
  • Set Allow All Other Fields to enabled.

Given these rule at the document level, insert and update operations that result in documents where "about.count.words" field is greater than 0 as well as delete operations of documents where "about.count.words" field is greater than 0. For example, the following StitchClient write operations are allowed:

db.getCollection("reports").insert(
   {
     "title": "Apples",
     "classification": "Public",
     "views": 101,
     "about": { "subject": "fruit", "counts": { "pages": 10, "words": 500 } }
    }
);
db.getCollection("reports").updateMany(
   { "classification":"Public", "about.counts.words": { "$gt": 0 } },
   { "$inc": { "views": 1 } }
);
db.getCollection("reports").deleteOne( { "about.counts.words": 1 } );

Only Specific Embedded Fields Are Writable

Note

Query predicates do not match any documents if the predicates include fields that are determined unreadable by the read rules. For simplicity, the following examples assume all fields are readable. See MongoDB Service Read Rule for more information on read rules.

This example sets up MongoDB Stitch rules to make the about.counts field and its embedded fields writable.

To be able to write specific embedded fields,

  • Ensure that no write rule exists at the document level.

  • Set Allow All Other Fields to enabled and modify the write rule to { "%%true": false } to ensure that unlisted fields are readable but not writable.

  • Specify the fields to which you wish to apply the rule. If the field is an embedded document or a field in the embedded document, you must add all the fields in that embedded document, even if you are not specifying rules for all. In this example, add:

    Field Field Type Write Rule
    about Object Do not specify a rule.
    about.subject Any Do not specify a rule.
    about.counts Object {}
  • In the about.counts document, set Allow All Other Fields to enabled. Do not specify a rule. Alternatively, you can explicitly add about.counts.pages and about.counts.words in the about.counts document. For more information, see Fields Specification.

Given these rule, you can:

  • Update the about.counts and its embedded fields only.
  • Replace a document that only contains the _id field, about.counts and its listed embedded fields with a replacement document that only contains the _id field (immutable), about.counts and its embedded fields.
  • Insert documents that only contains about.counts and its listed embedded fields.
  • Delete documents that only contains _id field, about.counts and its listed embedded fields.

For example, the following StitchClient write operations are allowed:

Note

If a write operation modifies multiple documents and one of the document violates the write rules, the write operation stops upon error and does not continue processing any remaining documents. This can occur if you add write rules to an existing collection with documents that may violate the new write rules. For details, see Stop on Error Behavior.

db.getCollection("reports").insert( { "about": { "counts": { "pages": 10, "words": 500 } } } );
db.getCollection("reports").updateMany( { "classification":"Public" }, { "$set": { "about.counts.words": 550 } } );
db.getCollection("reports").deleteMany(
   { "title": { "$exists": false }, "views": { "$exists": false }, "classification": { "$exists": false }, "about.subject": { "$exists": false } }
);

However, write operations that attempt to modify fields that are not writable are not allowed. For example, the following write operations are disallowed on the example collection which contains existing documents that may violate the new write rules:

db.getCollection("reports").insert( { "about": { "subject": "cookies", "counts": { "pages": 10, "words": 500 } } } );
db.getCollection("reports").updateMany( { "classification":"Public" }, { "$inc": { "views": 1 } } );
db.getCollection("reports").deleteMany( { "classification":"Public" } );

Specify Different Write Rules for Fields

Note

Query predicates do not match any documents if the predicates include fields that are determined unreadable by the read rules. For simplicity, the following examples assume all fields are readable. See MongoDB Service Read Rule for more information on read rules.

This examples sets up MongoDB Stitch rules such that:

  • title field is writable if before the write operation, the about.subject is "pies".
  • about.counts and all its embedded fields are writable if after the write operation, about.counts.words value is greater than 0.
  • about.subject is writable.

To set up the rules:

  • Ensure that no write rule exists at the document level.

  • Set Allow All Other Fields to enabled and modify the write rule to { "%%true": false } to ensure that unlisted fields are readable but not writable.

  • Specify the fields to which you wish to apply the rule. If the field is an embedded document or a field in the embedded document, you must add all the fields in that embedded document, even if you are not specifying rules for all. In this example, add:

    Field Field Type Write Rule
    title Any {"%%prevRoot.about.subject":"pies"}
    about Object Do not specify a rule.
    about.subject Any {}
    about.counts Object { "%%this.words": {"%gt": 0} }
  • In the about.counts document, set Allow All Other Fields to enabled. Do not specify a rule. Alternatively, you can explicitly add about.counts.pages and about.counts.words in the about.counts document. For more information, see Fields Specification.

Note

If a write operation modifies multiple documents and one of the document violates the write rules, the write operation stops upon error and does not continue processing any remaining documents. This can occur if you add write rules to an existing collection with documents that may violate the new write rules. For details, see Stop on Error Behavior.

Given these rules, you can:

  • Update the about.counts and its embedded fields only.
  • Replace a document that only contains the _id field, about.counts and its listed embedded fields with a replacement document that only contains the _id field (immutable), about.counts and its embedded fields.
  • Insert documents that only contains about.counts and its listed embedded fields.
  • Delete documents that only contains _id field, about.counts and its listed embedded fields.

For example, the following StitchClient write operations are allowed:

db.getCollection("reports").insert( { "about": { "counts": { "pages": 2, "words": 1000 } } } );
db.getCollection("reports").updateMany(
   { "classification":"Public", "about.subject": "pies" },
   { "$set": { "about.subject": "pudding", "title": "Chocolate Puddings", "about.counts": { "words": 500, "pages": 1 } } }
);
db.getCollection("reports").deleteMany( {
   "about.counts.pages": 1,
   "title": { "$exists": false },
   "views": { "$exists": false },
   "classification": { "$exists": false },
   "about.subject": { "$exists": false }
});

However, write operations that attempt to modify fields that are not writable are not allowed. For example, the following write operations are disallowed on the example collection:

db.getCollection("reports").insert( { "about": { "counts": { "pages": 10, "words": 0 } } } );
db.getCollection("reports").updateMany( { "about.subject": "cupcakes" }, { "$set": { "title": "Small Cakes", "about.counts": { "words": 500, "pages": 2 } } } );
db.getCollection("reports").deleteMany( {
   "about.counts.words": 0,
   "title": { "$exists": false },
   "views": { "$exists": false },
   "classification": { "$exists": false },
   "about.subject": { "$exists": false }
 });