2

I've been working on a project that uses mongodb to store data. In the past I've always used SQL but thought I would try our mongodb. Now that the code is written and the site is live and running I'm starting to wonder if I designed the db efficiently. The whole site uses one schema but I'm wondering if it would have been cleaner to use multiple schema.

The accounts[].reservations[], accounts[].listings[].messages[] and accounts[].listings[].prices[] are going to get really large and I've found that because I have so many objects inside of arrays of objects it's difficult to set/update things. How could I lay this out better?

Here's what I got:

var Account = new Schema({
    username: String,
    password: String,
    created: {type: Date, default:Date.now},
    accounts: [
        {
            type: {type: String, default: "Airbnb"}, // Airbnb, VRBO....
            airbnbUsername: String,
            airbnbPassword: String,
            airbnbUserID: String,
            airbnbAccessToken: String,
            lastLoginAttemptSuccessful: {type: Boolean, default: false},
            listings: [
                {
                    id: String,
                    airbnbName: String,
                    airbnbCheckInTime: Number,
                    airbnbCheckOutTime: Number,
                    airbnbListingID: String,
                    airbnbTimeZone: String,
                    nickname: String,
                    pricesUpdatedLast: Date,
                    pricingEnabled: {type: Boolean, default: false},
                    minPrice: Number,
                    rules: {
                        messages: [
                            {
                                message: String,
                                title: String,
                                event: String,
                                days: Number,
                                time: Number,
                                minNights: {type: Number, default: 1},
                                lastMinuteMessage: {type: String, default: ""},
                                lastMinuteMessageEnabled: {type: Boolean, default: false},
                                reviewEnabled: {type: Boolean, default: false},
                                reviewMessage: String,
                                sendMessageAfterLeavingReview: Boolean,
                            }
                        ], // messages
                        pricing: [
                            {
                                title: String,
                                scale: String, //(Fixed Value, Gradual Value, Fixed Percentage, Gradual Percentage)
                                amount: Number,
                                event: String, // floatingPeriod, orphanPeriod, specificDates, weekends, weekdays
                                floatingPeriodStartDay: Number,
                                floatingPeriodLength: Number,
                                orphanPeriodLength: Number,
                                specificDatesStartDate: Date,
                                specificDatesEndDate: Date,
                            }
                        ] // pricing
                    }, // rules
                    messages: [
                        {
                            messageRuleID: String,
                            airbnbConfirmationCode: String,
                            disable: {type: Boolean, default:false},
                            message: String,
                            sentDate: Date,
                            sentEvent: String,
                            sentDateFormated: String,
                            sentTimeFormated: String,
                            review: String,
                        }
                    ], // messages
                    prices: [
                        {
                            created: {type: Date, default:Date.now},
                            airbnbDate: String,
                            airbnbNativePrice: Number,
                            airbnbNativeSuggestedPrice: Number,
                            airbnbNativeSuggestedPricePercentage: Number,
                            airbnbNativeSuggestedPriceLevels: [{type: Number}],
                            airbnbAvailable: Boolean,
                        }
                    ] // prices
                }
            ], // listings
            reservations: [
                {
                    airbnbThreadID: String,
                    airbnbConfirmationCode: String,
                    airbnbListingID: String,
                    airbnbStartDate: String,
                    airbnbNights: Number,
                    airbnbFirstName: String,
                    airbnbStatus: String,
                    airbnbThumbnailUrl: String,
                }
            ] // reservations
        } // accounts
    ]
});

I just recently open sourced the project if you want to check out more the the code. It's an auto messaging and pricing engine for airbnb hosts:

https://github.com/wootwoot1234/Superhost-Tools

TylerH
  • 20,799
  • 66
  • 75
  • 101
Dev01
  • 13,292
  • 19
  • 70
  • 124
  • The one thing you do not want to do here is "embed arrays within arrays". There are real limitations and problems with this, as is summarized in the documentation of the [positional `$` operator](https://docs.mongodb.com/manual/reference/operator/update/positional/#nested-arrays) but you can also search for more reading on that subject. As general summary to the philosophy, I have some dot points on this answer [Mongoose populate vs object nesting](https://stackoverflow.com/a/24096822/2313887) where again you can find more information on the points presented there by searching for them. – Neil Lunn May 28 '17 at 02:41
  • @NeilLunn Thanks for the links. I'll check them out but do you think I should look into using a different type of db? – Dev01 May 28 '17 at 02:44
  • Generally though, what you are asking here in the context of a Question on this site is a bit too broad. Much as is inferred in the response linked earlier, the best schema design for your application always depends on your application's particular usage patterns. As my general rule of thumb, I ask myself *'what information needs to be presented on one page?"*. And in MongoDB context this generally gives some guide as to which relationships should be embedded and which can reside elsewhere. Then I consider updating that data and see if the requirements change. – Neil Lunn May 28 '17 at 02:46
  • Now if you are going to start asking *"Which database?"* then you are not only moving from "too broad" but also into "Primarily opinion based". IMHO, if you really don't know **why** you are using MongoDB and are already comfortable with an RDBMS, then MongoDB is probably not for you. Once you run into problems using a relational pattern, that's when you should be looking at other storage options. Of course mileage and opinions on that may largely differ. – Neil Lunn May 28 '17 at 02:49

0 Answers0