Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Different timestamp behaviour for different operators on nested subdocuments #12119

Closed
2 tasks done
lx-0 opened this issue Jul 18, 2022 · 1 comment · Fixed by #12151
Closed
2 tasks done

Different timestamp behaviour for different operators on nested subdocuments #12119

lx-0 opened this issue Jul 18, 2022 · 1 comment · Fixed by #12151
Labels
confirmed-bug We've confirmed this is a bug in Mongoose and will fix it.
Milestone

Comments

@lx-0
Copy link

lx-0 commented Jul 18, 2022

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the bug has not already been reported

Mongoose version

6.3.3

Node.js version

12

MongoDB server version

4.5

Description

When updating a nested document array, the timestamps of the nested documents are only updated in certain cases.

When using findOneAndUpdate and updating the nested document via $set operator, the timestamps are not updated in certain cases even if the timestamps option is enabled on the child schema.

Automatic update of the timestamps on the deepest schema only works if either all nodes in-between have option timestamp: true OR when using the $push operator.

This is due to function applyTimestampsToSingleNested (and respectively applyTimestampsToDocumentArray) exiting too early when the timestamp option on the current node is not set, ignoring all child nodes from there.

  import mongoose from "mongoose";

  // `timestamps` option set to true on deepest sub document
  const ConditionSchema = new mongoose.Schema(
    {
      kind: String,
      amount: Number,
    },
    { timestamps: true },
  );

  // no `timestamps` option defined
  const ProfileSchema = new mongoose.Schema({
    conditions: {
      type: [ConditionSchema],
    },
  });

  const UserSchema = new mongoose.Schema(
    {
      name: String,
      profile: {
        type: ProfileSchema,
      },
    },
    { timestamps: true },
  );

  const User = mongoose.model("User", UserSchema);

Steps to Reproduce

// $set does not update timestamps when inserting / replacing whole node
User.findOneAndUpdate(
          { name: 'Xyz' },
          { $set: { profile: {conditions: [{ kind: 'price', amount: 10 }] } } },
);
// $push does update timestamps when inserting to node
User.findOneAndUpdate(
          { name: 'Xyz' },
          { $push: { 'profile.conditions': { kind: 'price', amount: 10 } } },
);

Expected Behavior

Timestamps should also update on nested subdocuments.

@vkarpov15 vkarpov15 added this to the 6.4.8 milestone Jul 20, 2022
@IslandRhythms IslandRhythms added the confirmed-bug We've confirmed this is a bug in Mongoose and will fix it. label Jul 22, 2022
@IslandRhythms
Copy link
Collaborator

On my end the timestamps are being removed on both instances.

const mongoose = require('mongoose');

 // `timestamps` option set to true on deepest sub document
 const ConditionSchema = new mongoose.Schema(
    {
      kind: String,
      amount: Number,
    },
    { timestamps: true },
  );

  // no `timestamps` option defined
  const ProfileSchema = new mongoose.Schema({
    conditions: {
      type: [ConditionSchema],
    },
  });

  const UserSchema = new mongoose.Schema(
    {
      name: String,
      profile: {
        type: ProfileSchema,
      },
    },
    { timestamps: true },
  );

  const User = mongoose.model("User", UserSchema);

  async function run() {
    await mongoose.connect('mongodb://localhost:27017');
    await mongoose.connection.dropDatabase();

    await User.create({
        name: 'Test Testerson',
        profile: {
            conditions: {
                kind: 'Person',
                amount: 1
            }
        }
    });
    const entry = await User.findOne();

    console.log('Start', entry);
    console.log(entry.profile.conditions[0]);

    const set = await User.findOneAndUpdate(
        { name: 'Test Testerson' },
        { $set: { profile: {conditions: [{ kind: 'price', amount: 10 }] } } },
    );

    const setTest = await User.findOne();
    console.log('Set', setTest);
    console.log('CONDITIONS', setTest.profile.conditions[0]); // missing timestamps

    const push = await User.findOneAndUpdate(
        { name: 'Test Testerson' },
        { $push: { 'profile.conditions': { kind: 'price', amount: 10 } } }, 
    );

    const pushTest = await User.findOne();

    console.log('push', pushTest);
    console.log(pushTest.profile.conditions[0]); // missing timestamps
  }

  run();

vkarpov15 added a commit that referenced this issue Jul 26, 2022
… timestamps: true but parent schema does not

Fix #12119
vkarpov15 added a commit that referenced this issue Jul 27, 2022
fix(timestamps): set timestamps on child schema when child schema has timestamps: true but parent schema does not
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
confirmed-bug We've confirmed this is a bug in Mongoose and will fix it.
Projects
None yet
3 participants