Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MongoError: The dotted field .. is not valid for storage

I am trying to update a document with a matching nested attribute with the following query

upsertByCommentThreadId: function(commentThread) {
    return CommentThreads.update({
         'youtube.commentThreadId': commentThread.youtube.commentThreadId 
      },
      {
        $set: commentThread
      },
      {
        upsert: true
      }
    );
  }

Schema:

Schema({
  youtube: {
    type: Object
  },
  'youtube.etag': {
    type: String
  },
  'youtube.commentThreadId': {
    type: String,
    index: 1
  },
  ...

But I get an error

Exception while invoking method ... MongoError: The dotted field 'youtube.commentThreadId' in 'youtube.commentThreadId' is not valid for storage.

Im not sure how else I can query nested attributes, if not through dot notation

like image 419
Tarlen Avatar asked May 03 '15 13:05

Tarlen


3 Answers

It's the restrictions on field name before mongo 3.6 , now you can update mongo server to version 3.6 or higher to solve this problem.

https://docs.mongodb.com/manual/reference/limits/#naming-restrictions

like image 117
chroming Avatar answered Nov 11 '22 23:11

chroming


The error occurs because MongoDB cannot work when there are dots present in the key. A similar error,

MongoError: The dotted field '2016.11.14' in 'myData.days.2016.11.14' is
            not valid for storage.

occurs when the code is:

day = "2016.11.14"
myData.days[ day ] = 11

When the data is changed to

day = "2016_11_14"

The problem is fixed.

like image 23
Gerd Avatar answered Nov 11 '22 23:11

Gerd


You need to flatten your $set operator param:

schema.update( {
  'youtube.commentThreadId': commentThread.youtube.commentThreadId
},
{
  $set: {
    // Here is my change
    'youtube.commentThreadId': commentThread.youtube.commentThreadId
  }
},
{ /* opts */});

You're not showing your commentThread (input param for that upsertByCommentThreadId() function - but I suspect you are sending the object, judging by that query part. Example, you have:

let commentThread = {
  youtube: {
    commentThreadId: 12345
  }
};

So your query part is ok, but the $set expects a simple key:value, where key must be a string.

So, you are sending something like:

CommentThreads.update({

     // Here it's ok, as it's translated to:
     // { 'youtube.commentThreadId': 12345 }
     'youtube.commentThreadId': commentThread.youtube.commentThreadId 
  },
  {

    // but this gets expanded to a deeply nested object, like:
    // { $set: { youtube: {commentThreadId: 12345}}} 
    $set: commentThread
  },
  {/* opts */}
);

So, your $set operator wants a simple { key: value }, where key is a string.

like image 3
Zlatko Avatar answered Nov 12 '22 01:11

Zlatko