eherve / mongoose-datatable

Server side dataTable request support for mongoose
MIT License
42 stars 28 forks source link

MongoError: exception: dotted field names are only allowed at the top level #20

Closed ricardofbarros closed 10 years ago

ricardofbarros commented 10 years ago

Okay so I have my model structure like this for example

phones : {
    number : String,
    campaign_id: Number,
    usedBy : [{
       some_field : String,
       time : Date
    }],
    insertedBy: [{
        numberDestiny : String
        time : Date
    }]
}

And Im trying to filter 'insertedBy.time', and your plugin constructs this query

db.phones.aggregate(
[
 { '$match': { '$and': [ { 'insertedBy.numberDestiny': { '$in': [ /test/i ] } } ] } },
  { '$sort': { number: 1 } },
  { '$skip': 0 },
  { '$limit': 10 },
  { '$unwind': '$insertedBy' },
  { '$match': { 'insertedBy.numberDestiny': { '$in': [ /test/i ] } } },
  { '$group': 
     { _id: 
        { _id: '$_id',
          number: '$number',
          campaign_id: '$campaign_id',
          'usedBy.callcenter_id': '$usedBy.callcenter_id',
          'usedBy.time': '$usedBy.time' },
       insertedBy: { '$push': '$insertedBy' } } },
  { '$project': 
     { _id: '$_id._id',
       insertedBy: 1,
       number: '$_id.number',
       campaign_id: '$_id.campaign_id',
       'usedBy.callcenter_id': '$_id.usedBy.callcenter_id',
       'usedBy.time': '$_id.usedBy.time' } },
  { '$project': 
     { number: 1,
       'insertedBy.numberDestiny': 1,
       campaign_id: 1,
       'insertedBy.time': 1,
       'usedBy.callcenter_id': 1,
       'usedBy.time': 1 } } 

]

)

which gives me this nasty error,

Error("Printing Stack Trace")@:0
()@src/mongo/shell/utils.js:37
([object Array])@src/mongo/shell/collection.js:866
@(shell):30

uncaught exception: aggregate failed: {
    "errmsg" : "exception: dotted field names are only allowed at the top level",
    "code" : 16405,
    "ok" : 0
}

Well I tweaked (joined 2 fields) the query generated from your plugin and got to something like this, which the output given is perfect

db.phones.aggregate(
[
 { '$match': { '$and': [ { 'insertedBy.numberDestiny': { '$in': [ /tes/i ] } } ] } },
  { '$sort': { number: 1 } },
  { '$skip': 0 },
  { '$limit': 10 },
  { '$unwind': '$insertedBy' },
  { '$match': { 'insertedBy.numberDestiny': { '$in': [ /tes/i ] } } },
  { '$group': 
     { _id: 
        { _id: '$_id',
          number: '$number',
          campaign_id: '$campaign_id',
          usedBy : '$usedBy' },
       insertedBy: { '$push': '$insertedBy' } } },
  { '$project': 
     { _id: '$_id._id',
       insertedBy: 1,
       number: '$_id.number',
       campaign_id: '$_id.campaign_id',
       'usedBy.callcenter_id': '$_id.usedBy.callcenter_id',
       'usedBy.time': '$_id.usedBy.time' } },
  { '$project': 
     { number: 1,
       'insertedBy.numberDestiny': 1,
       campaign_id: 1,
       'insertedBy.time': 1,
       'usedBy.callcenter_id': 1,
       'usedBy.time': 1 } } 

]

)

My question here, is there any "right" way to do this type of stuff with your plugin ?

This can be usefull, the req.query has this keys,

  mDataProp_1: 'insertedBy.numberDestiny',
  sSearch_1: '3443',
  bRegex_1: 'false',
  bSearchable_1: 'true',

I just dont know if this is the proper way to send the query string to work with your plugin, If not I'm going to make pull request to resolve this issue.

ricardofbarros commented 10 years ago

Okay I found a fix for this thing, for what I understood this only happens on Array-Objects, you have a property called arrayPath, I just added that to group._id and everything works perfectly, well you will undertand better on the pull request

eherve commented 10 years ago

Thank you for the patch