title: Create or update field after pre validation middlewares?
body: <p>I'm trying to create a "findOneAndUpdate" query that would fire pre-validate middleware.  </p>
  
  <p>These middlewares are needed to validate the given coordinates and create an 'id' field (yes, <strong>not</strong> the '_id' one) when it isn't provided in the request's body.</p>
  
  <p>As you can see below (<em>see comments in the code</em>), I'm close, but don't understand why the error thrown by <code>mongo</code> is the duplicate key variety.</p>
  
  <p>Maybe promises aren't the way to go here, though they allowed me to come accomplish way more than chained <code>pre</code> middlewares.</p>
  
  <p><em>Here is my Express route:</em></p>
  
  <pre><code>/* POST /geolocs */
  router.post('/', function(req, res, next) {
  
    Geoloc.create(req.body, function(err, post) {
      if (err) return next(err);
  
      res.status(201).json(post);
    });
  });
  </code></pre>
  
  <p><em>Here is my schema:</em></p>
  
  <pre><code>var GeolocSchema = new mongoose.Schema({
    id: {
      type: String,
      required: true,
      unique: true
    },
    location: {
      type: {
        type: String,
        default: 'Point',
        required: true
      },
      coordinates: {
        type: [Number],
        required: true
      }
    },
    count: Number
  });
  
  GeolocSchema.index({
    location: '2dsphere'
  });
  </code></pre>
  
  <p><em>The pre validation middlewares:</em></p>
  
  <pre><code>// Before validation, check given coordinates for errors.
  GeolocSchema.pre('validate', function(next) {
    coord = this.location.coordinates
    if (this.location.type &amp;&amp; coord) {
      if (Array.isArray(coord) &amp;&amp; coord.length === 2) {
        lat = coord[1];
        lon = coord[0];
        if ((-90 &lt;= lat &amp;&amp; lat &lt;= 90) &amp;&amp; (-180 &lt;= lat &amp;&amp; lat &lt;= 180)) next();
      }
    }
    var err = new Error('...'); // Long error text, irrelevant here
    err.status = 400;
    next(err);
  });
  
  // Then, if no 'id' is given, create it.
  GeolocSchema.pre('validate', function(next) {
    if (!this.id) {
      strLat = this.location.coordinates[1].toFixed(3).replace('.', '_');
      strLon = this.location.coordinates[0].toFixed(3).replace('.', '_');
      this.id = strLat + '-' + strLon;
    }
    next();
  });
  </code></pre>
  
  <p>What I would love to be able to do is add the following below the above:</p>
  
  <pre><code>// Here, using the validate or save hook doesn't change anything.
  GeolocSchema.pre('validate', function(next) {
    var prom = Geoloc.findOne({
      'id': {
        $eq: this.id
      }
    }).exec();
  
    prom.then((err, geoloc) =&gt; {  // Arrow function here to access 'this'
      if (err) next(err);
      // If no geoloc was found, go ahead and save.
      if (!geoloc) next();
  
      // Else, update to increment the count (THIS WORKS).
      return Geoloc.update({'id': this.id}, {$inc: {count: 1}}).exec();
  
    }).then((toto) =&gt; {    
      // This doesn't work, the error thrown by mongo is a duplicate key error (E11000).
      if (toto) next(new Error('204'));
      else next(new Error("Something that shouldn't happen, happened..."));
    });
  });
  </code></pre>