Meteor-Community-Packages / meteor-collection2

A Meteor package that extends Mongo.Collection to provide support for specifying a schema and then validating against that schema when inserting and updating.
https://packosphere.com/aldeed/collection2
MIT License
1.02k stars 108 forks source link

Problem with "positioned filtered operator" in meteor schema #387

Closed inoyatov closed 5 years ago

inoyatov commented 6 years ago

I have following document (I cannot change structure of document)

[
   {
      "_id":"pjWtu2E3emehyo2WF",
      "name":"11st",
      "products":[
         {
            "name":"Blackboard"
         },
         {
            "name":"Marker"
         }
      ]
   },
   {
      "_id":"h4YgXTtks27DSqgbE",
      "name":"amazon",
      "products":[
         {
            "name":"Blackboard"
         }
      ]
   }
]

Schema for this document declared as following:

Schema = {}                                                                                                                                                                                                        

Schema.Property = new SimpleSchema (                                                                                                                                                                               
  name:                                                                                                                                                                                                            
    type: String                                                                                                                                                                                                   
  value:                                                                                                                                                                                                           
    type: String                                                                                                                                                                                                   
  type:                                                                                                                                                                                                            
    type: String                                                                                                                                                                                                   
)                                                                                                                                                                                                                  

Schema.Product = new SimpleSchema (                                                                                                                                                                                
  name:                                                                                                                                                                                                            
    type: String                                                                                                                                                                                                   
  properties:                                                                                                                                                                                                      
    type: [Schema.Property]                                                                                                                                                                                        
    defaultValue: []                                                                                                                                                                                               
    optional: true                                                                                                                                                                                                 
)                                                                                                                                                                                                                  

Schema.Store = new SimpleSchema (                                                                                                                                                                                  
  name:                                                                                                                                                                                                            
    type: String                                                                                                                                                                                                   
  products:                                                                                                                                                                                                        
    type: [Schema.Product]                                                                                                                                                                                         
    defaultValue: []                                                                                                                                                                                               
    optional: true                                                                                                                                                                                                 
)                                                                                                                                                                                                                  

Stores.attachSchema Schema.Store 

Now I want to add property into Marker.properties of "11st" store. So, in mongo client console I could use positioned filtered operator $[<idetifier>] for mongodb update function.

>db.stores.update(
  {"_id": "pjWtu2E3emehyo2WF"},
  {$push: {"products.$[product].properties": {"name": "color",  "type": "string",  "value": "red"}}}, 
  {arrayFilters: [{"product.name": "Marker"}]}
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

However Meteor update function only accepts function as following

Mongo.Collection#update(selector, modifier, [options], [callback])

according to documenation. First parameter is select, second is modifier. However, as far as I understood arrayFilters is third parameter to update function which is not defined in meteor, but I created server method as following:

  "store.addProperty": (storeId, productName, propertyName, propertyType, propertyValue) ->
    try 
      Stores.update storeId, $push: {"products.$[product].properties": {"name": propertyName, "type": propertyType, "value": propertyValue}}, {"arrayFilters": [{"product.name": productName}]}
    catch error
      return error.message
    return "Success"

After calling this server side method from client i got following error message:

products.$[product].properties.0 is not allowed by the schema

How I can achieve same result as in meteor console? Can some one help? Is there is solution for that? P.S: My mongo db 4.0.0 and Meteor 1.7.0.3

ivansglazunov commented 5 years ago

+1

aldeed commented 5 years ago

The one issue is making sure Meteor collection supports arrayFilters, which it does not yet according to the linked issue.

The schema validation error is because SimpleSchema package does not yet parse and understand arrayFilter placeholders. The workaround would be to disable validation for each update that uses arrayFilters.

But this is a SimpleSchema issue, so please submit this issue in that repo (or search and +1 existing issue): https://github.com/aldeed/simple-schema-js/issues