пн goose сохранение многоуровневых вложенных объектов - PullRequest
1 голос
/ 13 марта 2020

Я пытаюсь реализовать мой первый REST API на основе mon goose.

Я пробовал несколько дней, но не могу его запустить. Я хотел бы сохранить опрос с массивом элементов управления и для каждого элемента управления массив ControlProperties.

В различных сценариях ios Я получил его для сохранения опроса с массивом элементов управления, но без controlProperties, а иногда даже без массив элементов управления.

Может кто-нибудь помочь мне понять мою ошибку?

Большое спасибо.

Структура выглядит следующим образом:

Survey - Array of control - Массив controlProperty

Мои файлы схемы:

опрос. js

const mongoose = require('mongoose');
const Control = require('./control');

const surveySchema = mongoose.Schema({
    _id: mongoose.Schema.Types.ObjectId,
    name: {
        type: String,
        required: true,
        min: 4,
        max: 255
    },
    description: {
        type: String,
        required: false,
        max: 1000
    },
   closeDate: {
       type: Date,
       required: false
   },
   controls: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Control' }]
});

module.exports = mongoose.model('Survey', surveySchema);

control. js

const mongoose = require('mongoose');
const Survey = require('./survey');

const controlSchema = new mongoose.Schema({
    _id: mongoose.Schema.Types.ObjectId,
    survey: {type: mongoose.Schema.Types.ObjectId, ref: 'Survey'},
    controlType: {
        type: String,
        required: true
    },
    name: {
        type: String, 
        required: true
    },
    isInput: {
        type: Boolean,
        required: true

    },
    order: {
        type: Number,
        required: true
    },
    controlProperties: [{ type: mongoose.Schema.Types.ObjectId, ref: 'ControlProperty' }]
});


module.exports = mongoose.model('Control', controlSchema);

controlProperty. js

const mongoose = require('mongoose');
const Control = require('./control');

mongoose.Schema.Types.String.checkRequired(v => v != null);

const controlPropertySchema = new mongoose.Schema({
    _id: mongoose.Schema.Types.ObjectId,
    control: { type: mongoose.Schema.Types.ObjectId, ref: 'Control' },
    propertyName: {
        type: String,
        required: true
    },
    propertyValue: {
        type: String,
        required: true
    },
    order: {
        type: Number,
        required: true
    }

})

module.exports = mongoose.model('ControlProperty', controlPropertySchema);

Мой node.js код для получения почтовых данных:

/ маршруты / опрос. js

router.post("/", (req, res, next) => {


        Survey.find({ _id: req.body._id })
            .exec()
            .then(result => {
                if (result.length >= 1) {
                    return res.status(409).json({
                        message: "Survey exists"
                    });
                } else {

                    const survey = new Survey({
                        _id: new mongoose.Types.ObjectId(),
                        name: req.body.name,
                        description: req.body.description,
                        closeDate: req.body.closeDate,
                        order: req.body.order
                    });


                    let controlData = req.body.controls;
                    let arControls = [];

                    if(controlData != null) {

                        for (var i = 0, clen = controlData.length; i < clen; i++) {
                            let c = controlData[i];
                            let control = new Control({
                                _id: new mongoose.Types.ObjectId(),
                                controlType: c.controlType,
                                name: c.name,
                                isInput: c.isInput,
                                order: c.order
                            })

                            let controlPropertyData = c.controlProperties;
                            let arControlProperty = [];

                            if(controlPropertyData != null) {

                                for (var j = 0, cplen = controlPropertyData.length; j < cplen; j++) {
                                    let cp = controlPropertyData[j];
                                    let controlProperty = new ControlProperty({
                                        _id: new mongoose.Types.ObjectId(),
                                        propertyName: cp.propertyName,
                                        propertyValue: cp.propertyValue, 
                                        order: cp.order                                
                                    })

                                    arControlProperty.push(controlProperty);
                                }

                                ControlProperty.insertMany(arControlProperty, forceServerObjectId=true,function (err,data) {
                                    if(err!=null){
                                        return console.log(err);
                                    }
                                    console.log(" " + j + " controlProperties for control " + i +  " saved");

                                    control.controlProperties = data;
                                    console.log(data);
                                });


                            } 
                            arControls.push(control);


                        }

                        Control.insertMany(arControls, forceServerObjectId=true,function (err,data) {
                            if(err!=null){
                                return console.log(err);
                            }
                            survey.controls = data;

                            console.log("controls saved");
                            console.log(data);
                        });
                    }

                    survey
                        .save()
                        .then(result => {
                            console.log("survey saved");
                            res.status(201).json(survey);
                        })
                        .catch(err => {
                            console.log(err);
                            res.status(500).json({
                                error: err
                            });
                        });
                }

        });
    });

образец почтовых данных:

{   
    "name": "TestSurvey",
    "description": "This is a test survey",
    "controls":  [
        {       
            "controlType": "Label",
            "name": "Label1",
            "isInput": false,
            "order": 1,
            "controlProperties": [
                {
                    "propertyName": "FontSize", 
                    "propertyValue": "Large",
                    "order": 1
                },
                {
                    "propertyName": "BackgroundColor", 
                    "propertyValue": "Darkgreen",
                    "order": 2
                },
                {
                    "propertyName": "FontAttributes", 
                    "propertyValue": "Bold",
                    "order": 3
                },
                {
                    "propertyName": "HorizontalOptions", 
                    "propertyValue": "Fill",
                    "order": 4
                },
                {
                    "propertyName": "HorizontalTextAlignment", 
                    "propertyValue": "Center",
                    "order": 5
                },
                {
                    "propertyName": "TextColor", 
                    "propertyValue": "White",
                    "order": 6
                },
                {
                    "propertyName": "Text", 
                    "propertyValue": "Paris Work-Life Balance",
                    "order": 7
                }
            ]
        },
        {       
            "controlType": "Label",
            "name": "Label2",
            "isInput": false,
            "order": 2,
            "controlProperties": [
                {
                    "propertyName": "FontSize", 
                    "propertyValue": "Medium",
                    "order": 1
                },
                {
                    "propertyName": "Margin", 
                    "propertyValue": "20,0,20,0",
                    "order": 2
                },
                {
                    "propertyName": "FontAttributes", 
                    "propertyValue": "Bold",
                    "order": 3
                },
                {
                    "propertyName": "HorizontalOptions", 
                    "propertyValue": "StartAndExpand",
                    "order": 4
                },
                {
                    "propertyName": "HorizontalTextAlignment", 
                    "propertyValue": "Center",
                    "order": 5
                },
                {
                    "propertyName": "Text", 
                    "propertyValue": "Dear [[FirstName]], \nwas your workload on the case 12345 - 67(Company) compliant to the BCG Work Life Balance Ground Rules over the past week ?",
                    "order": 6
                }
            ]
        },
        {
            "controlType": "PWLBControl",
            "name": "PWLB1",
            "isInput": true,
            "order": 3,
            "controlProperties": [
                {
                        "propertyName": "Margin", 
                        "propertyValue": "20,0,20,0",
                        "order": 1
                }
            ]
        },      
        {
            "controlType": "Button",
            "name": "button1",
            "isInput": false,
            "order": 4,
            "controlProperties": [
                {
                    "propertyName": "Text", 
                    "propertyValue": "Submit",
                    "order": 1
                },
                        {
                    "propertyName": "HorizontalOptions", 
                    "propertyValue": "StartAndExpand",
                    "order": 2
                },
                {
                    "propertyName": "IsSubmitButton",
                    "propertyValue": true,
                    "order": 3
                }
            ]
        },
        {
            "controlType": "Image",
            "name": "image1",
            "isInput": false,
            "order": 5,
            "controlProperties": [
                {
                    "propertyName": "Source",
                    "propertyValue": "",
                    "order": 1
                },
                {
                    "propertyName": "VerticalOptions",
                    "propertyValue": "End",
                    "order": 2
                }
            ]
        }
    ]
}

Ответы [ 2 ]

1 голос
/ 14 марта 2020

Спасибо за ценный вклад.

Наконец я нашел причину, по которой мой код не работал с самого начала. Единственное, что мне нужно было изменить, это сделать присвоение массива controlProperties элементу управления и массива элементов управления для опроса не в функции успеха insertMany, а после всей команды insertMany.

Поэтому я изменил:

  ControlProperty.insertMany(arControlProperty, forceServerObjectId=true,function (err,data) {
      if(err!=null){
          return console.log(err);
      }
      console.log(" " + j + " controlProperties for control " + i +  " saved");

      control.controlProperties = data;
      console.log(data);
  });

до:

  ControlProperty.insertMany(arControlProperty, forceServerObjectId=true,function (err,data) {
      if(err!=null){
          return console.log(err);
      }
      console.log(" " + j + " controlProperties for control " + i +  " saved");

      console.log(data);
  });

  control.controlProperties = arControlProperty;

Спасибо за вашу поддержку.

1 голос
/ 13 марта 2020

Нет необходимости хранить отдельные коллекции для controlProperties и control. Вы можете встроить controlPropertySchema внутрь controlSchema и вставить controlSchema внутрь surveySchema. Таким образом, в конце у нас будет только одна коллекция для опроса.

Это позволит создать опрос за одну операцию вставки. А также вы сможете получить всю информацию об опросе за одну операцию чтения.

Также есть несколько предложений:

  1. Лучше не добавлять поля _id в схемы, mongodb справится с этим.
  2. Я вижу, вы используете его, если существует опрос с указанным _id. Лучше использовать поле name, чтобы проверить, существует ли опрос.
  3. min и max используются для числового типа, для строкового типа minlength и maxlength. Документы

Таким образом, surveySchema должно выглядеть следующим образом:

const mongoose = require("mongoose");

const controlPropertySchema = new mongoose.Schema({
  // _id: mongoose.Schema.Types.ObjectId,
  // control: { type: mongoose.Schema.Types.ObjectId, ref: "Control" },
  propertyName: {
    type: String,
    required: true
  },
  propertyValue: {
    type: String,
    required: true
  },
  order: {
    type: Number,
    required: true
  }
});

const controlSchema = new mongoose.Schema({
  //_id: mongoose.Schema.Types.ObjectId,
  //  survey: {type: mongoose.Schema.Types.ObjectId, ref: 'Survey'},
  controlType: {
    type: String,
    required: true
  },
  name: {
    type: String,
    required: true
  },
  isInput: {
    type: Boolean,
    required: true
  },
  order: {
    type: Number,
    required: true
  },
  controlProperties: [controlPropertySchema]
  //controlProperties: [{ type: mongoose.Schema.Types.ObjectId, ref: "ControlProperty" }]
});

const surveySchema = mongoose.Schema({
  // _id: mongoose.Schema.Types.ObjectId,
  name: {
    type: String,
    required: true,
    minlength: 4,
    maxlength: 255
  },
  description: {
    type: String,
    required: false,
    maxlength: 1000
  },
  closeDate: {
    type: Date,
    required: false
  },
  controls: [controlSchema]
  // controls: [{ type: mongoose.Schema.Types.ObjectId, ref: "Control" }]
});

module.exports = mongoose.model("Survey", surveySchema);

Теперь мы можем создать опрос с этим почтовым маршрутом: (Обратите внимание, что мы не делаем никаких преобразований, так как структура нашего тела запроса такая же, как surveySchema)

router.post("/surveys", async (req, res) => {
  try {
    let survey = await Survey.findOne({ name: req.body.name });

    if (survey) {
      return res.status(400).send("A survey already exists with that name");
    }

    const result = await Survey.create(req.body);
    res.send(result);
  } catch (err) {
    console.log(err);

    if (err.name === "ValidationError") {
      return res.status(400).send(err.errors);
    }
    res.status(500).send("Something went wrong");
  }
});

В теле вашего запроса был пустой propertyValue, поэтому я изменил его на "propertyValue": "I was empty", и также логическое значение вместо строки, поэтому я изменил его на "propertyValue": "I was true"

Вы можете использовать это исправленное тело запроса:

{
    "name": "TestSurvey",
    "description": "This is a test survey",
    "controls": [
        {
            "controlType": "Label",
            "name": "Label1",
            "isInput": false,
            "order": 1,
            "controlProperties": [
                {
                    "propertyName": "FontSize",
                    "propertyValue": "Large",
                    "order": 1
                },
                {
                    "propertyName": "BackgroundColor",
                    "propertyValue": "Darkgreen",
                    "order": 2
                },
                {
                    "propertyName": "FontAttributes",
                    "propertyValue": "Bold",
                    "order": 3
                },
                {
                    "propertyName": "HorizontalOptions",
                    "propertyValue": "Fill",
                    "order": 4
                },
                {
                    "propertyName": "HorizontalTextAlignment",
                    "propertyValue": "Center",
                    "order": 5
                },
                {
                    "propertyName": "TextColor",
                    "propertyValue": "White",
                    "order": 6
                },
                {
                    "propertyName": "Text",
                    "propertyValue": "Paris Work-Life Balance",
                    "order": 7
                }
            ]
        },
        {
            "controlType": "Label",
            "name": "Label2",
            "isInput": false,
            "order": 2,
            "controlProperties": [
                {
                    "propertyName": "FontSize",
                    "propertyValue": "Medium",
                    "order": 1
                },
                {
                    "propertyName": "Margin",
                    "propertyValue": "20,0,20,0",
                    "order": 2
                },
                {
                    "propertyName": "FontAttributes",
                    "propertyValue": "Bold",
                    "order": 3
                },
                {
                    "propertyName": "HorizontalOptions",
                    "propertyValue": "StartAndExpand",
                    "order": 4
                },
                {
                    "propertyName": "HorizontalTextAlignment",
                    "propertyValue": "Center",
                    "order": 5
                },
                {
                    "propertyName": "Text",
                    "propertyValue": "Dear [[FirstName]], \nwas your workload on the case 12345 - 67(Company) compliant to the BCG Work Life Balance Ground Rules over the past week ?",
                    "order": 6
                }
            ]
        },
        {
            "controlType": "PWLBControl",
            "name": "PWLB1",
            "isInput": true,
            "order": 3,
            "controlProperties": [
                {
                    "propertyName": "Margin",
                    "propertyValue": "20,0,20,0",
                    "order": 1
                }
            ]
        },
        {
            "controlType": "Button",
            "name": "button1",
            "isInput": false,
            "order": 4,
            "controlProperties": [
                {
                    "propertyName": "Text",
                    "propertyValue": "Submit",
                    "order": 1
                },
                {
                    "propertyName": "HorizontalOptions",
                    "propertyValue": "StartAndExpand",
                    "order": 2
                },
                {
                    "propertyName": "IsSubmitButton",
                    "propertyValue": "I was true",
                    "order": 3
                }
            ]
        },
        {
            "controlType": "Image",
            "name": "image1",
            "isInput": false,
            "order": 5,
            "controlProperties": [
                {
                    "propertyName": "Source",
                    "propertyValue": "I was empty",
                    "order": 1
                },
                {
                    "propertyName": "VerticalOptions",
                    "propertyValue": "End",
                    "order": 2
                }
            ]
        }
    ]
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...