skip to Main Content

It looks like it doesn’t like how I set the nested schema?

User Schema

const mongoose = require("mongoose");
    const twitchSchema = mongoose.Schema(
      {
        id: Number,
        login: String,
        display_name: String,
        type: String,
        broadcaster_type: String,
        description: String,
        profile_image_url: String,
        offline_image_url: String,
        view_count: Number,
        email: String,
        created_at: String,
        provider: String,
        accessToken: String,
        refreshToken: String,
      },
      { _id: false }
    );
    const userSchema = new mongoose.Schema({
      provider: {
        youtube: {},
        twitch: twitchSchema,
      },
    });
    module.exports = mongoose.model("User", userSchema);

This is how I create a new document

const userModels = new UserModels();
userModels.provider[profile.provider].login = profile.login;
const result = await userModels.save()

5

Answers


  1. You are using mongoose.Schema incorrect. This is called embeded documents in mongodb. You can define schema like following:

    const mongoose = require('mongoose');
    const { Schema } = mongoose;
    
    const twitchSchema = new Schema({
        id: Number,
        login: String,
        display_name: String,
        type: String,
        broadcaster_type: String,
        description: String,
        profile_image_url: String,
        offline_image_url: String,
        view_count: Number,
        email: String,
        created_at: String,
        provider: String,
        accessToken: String,
        refreshToken: String,
    });
    
    const userSchema = new Schema({
    provider: {
        youtube: {},
        twitch: [twitchSchema],
      },
    });
    
    module.exports = mongoose.model("User", userSchema);
    
    Login or Signup to reply.
  2. Try defining user schema like this :-

    const userSchema = new mongoose.Schema({
      provider: {
        youtube: {},
        twitch: [twitchSchema],
      },
    });
    
    Login or Signup to reply.
  3. There are a couple issues:

    • your schema definition has extra commas, missing ‘new’, and curly brackets, and an additional _id object just hanging out there.
    • youtube: {}, is not a valid schema type, should be youtube: Object for example, or define a schema for it! (see my next bullet)
    • You can’t nest one schema within another like this, see comment from Bhaskar. I’d suggest you define TwitchSchema and a YoutubeSchema separately, and combine them in a third UserSchema.
    • If you omit fields at doc creation ( only provide ‘login’ and omit others) the resulting document WILL NOT have any other fields. If that is not what you want, provide at least default empty values for all other fields as well.
    const mongoose = require('mongoose');
    main().catch(err => console.log(err));
    async function main() {
      await mongoose.connect('mongodb+srv://ADDYOURS');  // <--- add url
      const TwitchSchema = new mongoose.Schema({
        id: Number,
        login: String,
        display_name: String,
        type: String,
        broadcaster_type: String,
        description: String,
        profile_image_url: String,
        offline_image_url: String,
        view_count: Number,
        email: String,
        created_at: String,
        provider: String,
        accessToken: String,
        refreshToken: String
      });
      const YoutubeSchema = new mongoose.Schema({
        id: Number,
        login: String
      });
      const userSchema = new mongoose.Schema({
        id: Number,
        twitch : [TwitchSchema],
        youtube : [YoutubeSchema]
      });
    
      UserModels = mongoose.model("User", userSchema);
    
      const UserDocument = new UserModels();
    
      let profile = {
        provider : 'twitch',
        login : 'foobars'
      }
    
      UserDocument[profile.provider].push({ login : profile.login});
    
      console.log( UserDocument[profile.provider]);
      const result = await UserDocument.save()
    }
    

    The above results in the following document:

    enter image description here

    Login or Signup to reply.
  4. If I were you I would do something like this

    Define Schemas

    const TwitchSchema = new mongoose.Schema({
        twitchID: Number,
        login: String,
        display_name: String,
        type: String,
        broadcaster_type: String,
        description: String,
        profile_image_url: String,
        offline_image_url: String,
        view_count: Number,
        email: String,
        created_at: String,
        provider: String,
        accessToken: String,
        refreshToken: String
    });
    
    const YoutubeSchema = new mongoose.Schema({
        youtubeID: Number,
        login: String
    });
    
    
    const UserSchema = new mongoose.Schema({
        twitch: {
            type: Schema.Types.ObjectId,
            ref: 'Twitch'
        },
        youtube: {
            type: Schema.Types.ObjectId,
            ref: 'Youtube'
        }
    });
    
    const User = mongoose.model('User', UserSchema);
    const Twitch = mongoose.model('Twitch', TwitchSchema);
    const Youtube = mongoose.model('Youtube', YoutubeSchema);
    

    After this when I want to save the user and twitch value. I would do

    route.post('/fake-route', async (req, res) => {
        try {
            //let's assume I have all the value from twitch in the `twitchData` variable
            let twitchData = getTwitchData();
    
            // Save Twitch Data to Mongo
            const twitchSaveToDB = await Twitch.create(twitchData);
    
            //Now Save User data using above saved Twitch Data
            let userDataToSave = {
                twitch: twitchSaveToDB._id
            };
            const userToDB = await User.create(userDataToSave);
    
            res.status(201).json({
                message: 'User Created'
            });
        } catch (err) {
            console.error(err);
            res.status(500).json({
                message: 'Error Occured'
            });
        }
    
    })
    

    I didn’t test the code exactly, so there might be few things to fix here and there but this would be the general concept I would follow

    Login or Signup to reply.
  5. You should always add the error you are getting in your question. I have tried your code and got undefined reference error:

    // Schema setup
    
    const mongoose = require('mongoose');
    const twitchSchema = mongoose.Schema(
        {
            id: Number,
            login: String,
            display_name: String,
            type: String,
            broadcaster_type: String,
            description: String,
            profile_image_url: String,
            offline_image_url: String,
            view_count: Number,
            email: String,
            created_at: String,
            provider: String,
            accessToken: String,
            refreshToken: String,
        },
        { _id: false }
    );
    const userSchema = new mongoose.Schema({
        provider: {
            youtube: {},
            twitch: twitchSchema,
        },
    });
    
    module.export = mongoose.model('User', userSchema);
    
    // Driver code
    const u = new User();
    console.log(u);
    
    const profile = {
      provider: 'twitch',
      login: 'dummy_login',
    };
    
    u.provider[profile.provider].login = profile.login;
    console.log(u);
    
    const res = await User.create(u);
    console.info(res);
    
    // Error
    // { _id: new ObjectId("624e8901dc46c217a1461c41") }
    // TypeError: Cannot set property 'login' of undefined
    

    So the problem is while setting the login field in the user model. You should tweak your userSchema like this:

    const userSchema = new mongoose.Schema({
        provider: {
            youtube: {},
            twitch: { type: twitchSchema, default: {} },
        },
    });
    

    Please see mongoose documentation here.
    Now if you run the below driver code it is able to create the record in mongo.

    const u = new User();
    console.log(u);
    
    const profile = {
      provider: 'twitch',
      login: 'dummy_login',
    };
    
    u.provider[profile.provider].login = profile.login;
    console.log(u);
    
    const res = await User.create(u);
    console.info(res);
    

    See logs below:

    { _id: new ObjectId("624e8a9990d90dea47e7f62a") }
    {
      provider: { twitch: { login: 'dummy_login' } },
      _id: new ObjectId("624e8a9990d90dea47e7f62a")
    }
    {
      provider: { twitch: { login: 'dummy_login' } },
      _id: new ObjectId("624e8a9990d90dea47e7f62a"),
      __v: 0
    }
    

    user is created in mongo

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search