简体   繁体   中英

MongoDB: Can you include a collection as a field in a document of another collection?

I'm using Javascript, Node.js, Express and MongoDB to make a webapplication. In the application You can make an account with fields name and lastnames, but I also want a field that keeps track of completed steps (boolean: false if uncompleted, true if completed). It's not a possibility to hardcode the steps as separate boolean fields because I want to make the list of steps adjustable. So I was thinking of making another collection (=progress) with al the names of the steps and where you can add some and know I am searching for a way to include these boolean steps for each account I make.

sketch of how I think the MongoDB collection Schema's should look like:

account
- name (String)
- lastname (String)
- progress:
- stepName (String), completed (boolean)
- stepName (String), completed (boolean)
- stepName (String), completed (boolean)
-...

progress
- stepName (String)
- completed (boolean)

Many thanks in advance

You can -- since it looks like you are using Mongoose, you can see https://mongoosejs.com/docs/subdocs.html for some info on how to do something like you are outlining here.

However, based on my experience doing similar things (tracking progress through a flow), I would suggest setting things up a little differently. The biggest issue I see is that if you add a new step, you don't want to have to go through and update every account document to put the new step into its progress field. Or similarly, if you decide to remove a step, you don't want to have to go to each account and remove that step's entry from its progress field.

Instead of thinking of it as including the progress collection in each document of the account collection, I would think of it as having a step collection that contains any adjustable/configurable data about each step. There is no need to have a completed field there, because that's something specific to each account. Depending on your needs, I would suggest something like the following:

step
    - id (String) -- something that will never change
    - name (String) -- a user-facing name that you might want to change later
    - position (number) -- used to control the order of steps presented to the user
    - ... other things, depending on what you need/want

Now, for account , you will want a map ( https://mongoosejs.com/docs/schematypes.html#maps ) showing the progress (completion state of each step):

account
  - name (String)
  - lastname (String)
  - progress: (Map of boolean)
      - key: step id
      - value: boolean showing whether it has been completed
  - ...

This means any time you're checking an account's progress, you'll want to loop through the documents from the step collection (ordered based on the position field), and check that account's progress map against each step id to see if there are any that aren't completed. Although that sounds like extra work, there are a lot of advantages to this sort of approach. It means if you decide to add, remove, or reorder a step within the step collection, you don't need to go make the same change to every existing account document to match -- you'll just automatically pick up the change the next time you check the account's progress field.

One further note -- the way I'm suggesting you set up the schema, instead of having an explicit false value for each step that isn't completed, most of the time you just wouldn't have any value in the map for uncompleted steps. In your code, you can easily treat any missing step progress values the same as a false ( if (.account.progress.firstStep) { works by default with javascript). This also gives you the option, if you want, of setting a step's progress to explicitly false only when a user has been presented with that step. Thus you have some easier visibility into what step they stopped on (even if you later change the order of the steps) and/or if they've skipped any steps (if some are considered optional), rather than only being able to see which steps have been completed.

What you describe is called an "Embedded Document" and is supported by mongodb.

Mongodb documentation includes an example of what you want:

{
   ...
   name: { first: "Alan", last: "Turing" },
   contact: { phone: { type: "cell", number: "111-222-3333" } },
   ...
}

And in mongodb it's accessed by:

"<embedded document>.<field>"

Source: https://docs.mongodb.com/manual/core/document/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM