Как установить индекс при создании документа с Mongoose - PullRequest
0 голосов
/ 25 сентября 2019

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

Перед отправкой этой формы на сервер я конвертирую все в объект FormData.Учитывая, что у меня есть пользователь, который динамически добавляет 1 форму поверх формы по умолчанию, вот что get отправляет на сервер:

ПЕРВЫЙ Опыт работы

["company", "companyA"]

["positionExperience", "positionA"]

["descriptionExperience", "descriptionA"]

ВТОРОЙ Опыт работы

["company", "companyB"]

["positionExperience", "positionB"]

["descriptionExperience", "descriptionB"]


В бэкэнде моего приложения я получил почтовый маршрут для отправки формы, которая выглядит следующим образом:

personRoutes.post('/new', upload.single('file'), (req, res) => {
    const person = new Person({
        file: req.file.path,
        experience: [
            {
                company: req.body.company,
                positionExperience: req.body.positionExperience,
                descriptionExperience: req.body.descriptionExperience,
                websiteExperience: req.body.websiteExperience,
                timeperiodExperience: req.body.timeperiodExperience,
            }
        ],
    });
    person.save()
        .then()
        .catch()
});

Проблема в том, что req.body на стороне сервера выдвигает ответы в обеих формах в массиве.Чтобы продемонстрировать, что я имею в виду, это console.log из req.body

BODY:  [Object: null prototype] {
   company: [ 'companyA', 'companyB' ],
   positionExperience: [ 'positionA', 'positionB' ],
   descriptionExperience: [ 'descriptionA', 'descriptionB' ],
}

Так что в моем почтовом маршруте мне как-то нужно указать index для полей опыта.Кто-нибудь знает, как мне это сделать?Любая помощь очень ценится.

Спасибо

1 Ответ

1 голос
/ 25 сентября 2019

"Проблема в том, что req.body на стороне сервера помещает ответы на обе формы в массиве."

Это не совсем правильно,как это на самом деле клиент запрос, который на самом деле отправляется так.В основном это значение по умолчанию для x-www-form-urlencoded данных, когда вы отправляете более одного значения для указанного имени поля и отправляет то, что интерпретируется как массивы для каждого поля вместо массив представлений так, как вы ожидаете.

Мне кажется, что вы могли бы отправлять данные в более подходящем формате (то есть предварительно составленном JSON-представлении объекта, который вы на самом деле представляете)хотите), но вместо фактического изменения кода, который отправляет форму, вы всегда можете просто преобразовать то, что отправлено, в разумное представление того, что вы хотите фактически вставить для нового Person.

Предполагая, конечно,что единственные данные, присутствующие в req.body, относятся к части experience данных, которые будут добавлены, тогда простая инструкция преобразует это в массив записей, которые вы на самом деле хотите, а не просто все поля в виде массивов в том виде, в котором они есть на данный момент:

let data = req.body;

// For each total array length of a required field
let experience = [ ...Array(data.company.length)]
  Get all the keys of the input object  
  .map((e,i) => Object.keys(data)
    // Turn that into an object of singular values for the current index
    .reduce((o,e) => ({ ...o, [e]: data[e][i] }),{})
  )

ЕСЛИ у вас больше данных в req.body и вы хотите только какЭто специфические поля, тогда это просто простая модификация с Array.filter().Запускается в браузере из этого поста на этот раз:

   // Just simulating the content submitted in req.body
   let req = {
     body: {
        "company" : [
                "companyA",
                "companyB"
        ],
        "positionExperience" : [
                "positionA",
                "positionB"
        ],
        "descriptionExperience" : [
                "descriptionA",
                "descriptionB"
        ]
      }
    };
 

    // list of allowed fields
    let whitelist = [
      'company',
      'positionExperience',
      'descriptionExperience',
      'websiteExperience',
      'timeperiodExperience'
    ]

    // Remove all but the wanted fields
    let data = Object.entries(req.body)
      .filter(([k,v]) => whitelist.indexOf(k) != -1)
      .reduce((o,[k,v]) => ({ ...o, [k]: v }),{});

    let experience = [ ...Array(data.company.length)]
      .map((e,i) => Object.keys(data).reduce((o,e) => ({ ...o, [e]: data[e][i] }),{}))

    console.log(experience)

Либо там, где это были единственные клавиши ввода req.body, либо там, где вы извлекли только то, что хотели с помощью изменения выше, массив вывода experience будет(как показано на примере данных, показанных в вопросе, который будет добавлен не так, как предполагалось):

[
        {
                "company" : "companyA",
                "positionExperience" : "positionA",
                "descriptionExperience" : "descriptionA"
        },
        {
                "company" : "companyB",
                "positionExperience" : "positionB",
                "descriptionExperience" : "descriptionB"
        }
]

Это означает, что experience можно просто перенести в существующий код следующим образом:

const person = new Person({ file: req.file.path, experience });

Тогда, конечно, то, что будет сохранено, будет отражать ту же структуру:

{
  "file": "whateverFileNameSupplied",
  "experience": [
        {
                "company" : "companyA",
                "positionExperience" : "positionA",
                "descriptionExperience" : "descriptionA"
        },
        {
                "company" : "companyB",
                "positionExperience" : "positionB",
                "descriptionExperience" : "descriptionB"
        }
  ]
}

Лично я бы, вероятно, добавил бы smarts в интерфейс, чтобына самом деле представить данные в формате, который я действительно хочу.Но то, что у вас есть с массивами для каждого свойства, на самом деле типично для стандартного x-www-form-urlencoded запроса POST, и если вы еще не хотите тратить время на отправку запроса JSON, который фактически соответствует тому, что вы хотите сохранить, тогдапреобразование, как описано выше, обычно является вашим кратчайшим путем к выполнению.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...