Details

    • Type: New Feature New Feature
    • Status: Open Open
    • Priority: Major - P3 Major - P3
    • Resolution: Unresolved
    • Affects Version/s: None
    • Fix Version/s: Planning Bucket B
    • Component/s: Write Ops
    • Labels:
      None
    • Backport:
      No
    • # Replies:
      29
    • Last comment by Customer:
      true

      Description

      For maximum flexibility we should allow running arbitrary javascript code on each object during an update. It should probably run after other modifiers.

      update({_id: "foo"}. {$inc:

      {count: 1, total: 5}

      , $function: function()

      {this.avg = this.total / this.count}

      }

        Issue Links

          Activity

          Hide
          Anthony Hildoer
          added a comment - - edited

          +1 Oleg. This is a a great start. Not knowing much of how things are abstracted internally in Mongo, would this also work for findAndModify? If so, this covers our use case entirely.

          As for the requirement that the driver support a BSON encoded function, instead of a string. This is an alternative notation that may work for backwards compatibility with drivers that don't support that. Using your example, this alternative syntax would be:

          update({}, { $set: { computed: { $func: "return {value: this.a * this.b / this.c}" } } }, { upsert: false, multi: true } );

          (Please pardon the edits, I just found the "preview" button)

          Show
          Anthony Hildoer
          added a comment - - edited +1 Oleg. This is a a great start. Not knowing much of how things are abstracted internally in Mongo, would this also work for findAndModify? If so, this covers our use case entirely. As for the requirement that the driver support a BSON encoded function, instead of a string. This is an alternative notation that may work for backwards compatibility with drivers that don't support that. Using your example, this alternative syntax would be: update({}, { $set: { computed: { $func: "return {value: this.a * this.b / this.c}" } } }, { upsert: false, multi: true } ); (Please pardon the edits, I just found the "preview" button)
          Hide
          Moshe Simantov
          added a comment -

          Please consider security issues.
          This function should update only the current document and can't access any other documents or collections.

          Show
          Moshe Simantov
          added a comment - Please consider security issues. This function should update only the current document and can't access any other documents or collections.
          Hide
          Kevin J. Rice
          added a comment -

          Moshe Simatov makes a valid point about access control. Certainly having a query that accesses other collections would require some security consideration.

          Perhaps, then, we split this case into:

          • Do no other record accesses (this case)
          • Access other records, assuring proper access control is granted.

          I'm thinking of a use case where we're verify validity of a foreign key. TableOne:

          { ..., 't2fk1' : 12, ...}

          , TableTwo:

          { ..., 'fk1' : 12, ...}

          , etc.

          This would replicate the SQL query:

          • select t1.id, t1.fk1 from t1 where t1.fk1 not in (select t2.id from t2);

          RECOGNIZED OBJECTIONS: okay, so people will complain this isn't supposed to be a relational database, so we shouldn't have foreign keys. But, sometimes this is unavoidable for application-specific reasons. I need to be able to verify my foreign keys are valid.

          Show
          Kevin J. Rice
          added a comment - Moshe Simatov makes a valid point about access control. Certainly having a query that accesses other collections would require some security consideration. Perhaps, then, we split this case into: Do no other record accesses (this case) Access other records, assuring proper access control is granted. I'm thinking of a use case where we're verify validity of a foreign key. TableOne: { ..., 't2fk1' : 12, ...} , TableTwo: { ..., 'fk1' : 12, ...} , etc. This would replicate the SQL query: select t1.id, t1.fk1 from t1 where t1.fk1 not in (select t2.id from t2); RECOGNIZED OBJECTIONS: okay, so people will complain this isn't supposed to be a relational database, so we shouldn't have foreign keys. But, sometimes this is unavoidable for application-specific reasons. I need to be able to verify my foreign keys are valid.
          Hide
          Oleg Rekutin
          added a comment -

          Updates only apply to one collection, so you cannot access another collection anyway. There are no joins in MongoDB, so this is definitely out of scope.

          The Javascript function should only be updating one record at a time--not only is it a simpler implementation, but it is also cleaner conceptually. It allows the update to continue to be sharded and executed concurrently across shards.

          The new V8 engine in 2.4 restricts the ability to run database commands or access other data. See version 2.4 note here: http://docs.mongodb.org/manual/reference/operator/where/#op._S_where . FOr example "db" is not accessible. Therefore, there are already single-record access restrictions built-in.

          Show
          Oleg Rekutin
          added a comment - Updates only apply to one collection, so you cannot access another collection anyway. There are no joins in MongoDB, so this is definitely out of scope. The Javascript function should only be updating one record at a time--not only is it a simpler implementation, but it is also cleaner conceptually. It allows the update to continue to be sharded and executed concurrently across shards. The new V8 engine in 2.4 restricts the ability to run database commands or access other data. See version 2.4 note here: http://docs.mongodb.org/manual/reference/operator/where/#op._S_where . FOr example "db" is not accessible. Therefore, there are already single-record access restrictions built-in.
          Hide
          Anthony Hildoer
          added a comment - - edited

          I have to backup Oleg's response to Kevin regarding relational database like functionality.

          MongoDB's lack of relational database functionality is a technical decision, not political one against SQL. NoSQL purists don't avoid foreign key constraints (and multi-record atomic operations) just for the sake of being as NoSQL as possible. It is a fundamental shift which achieves performance and horizontal scalability that SQL solutions will never achieve without sacrificing vertical scale.

          My vote is -10000 for allowing IO in the $function method. Talking about foreign key enforcement/checking/whatever should be done within the context of the application, not the database server.

          Show
          Anthony Hildoer
          added a comment - - edited I have to backup Oleg's response to Kevin regarding relational database like functionality. MongoDB's lack of relational database functionality is a technical decision, not political one against SQL. NoSQL purists don't avoid foreign key constraints (and multi-record atomic operations) just for the sake of being as NoSQL as possible. It is a fundamental shift which achieves performance and horizontal scalability that SQL solutions will never achieve without sacrificing vertical scale. My vote is -10000 for allowing IO in the $function method. Talking about foreign key enforcement/checking/whatever should be done within the context of the application, not the database server.

            People

            • Votes:
              119 Vote for this issue
              Watchers:
              78 Start watching this issue

              Dates

              • Created:
                Updated:
                Days since reply:
                32 weeks, 1 day ago
                Date of 1st Reply: