Проблема с проверкой и добавлением элемента документа в коллекцию в MongoDB

#javascript #node.js #database #mongodb #mongoose

#javascript #node.js #База данных #mongodb #мангуст

Вопрос:

Я новичок в Nodejs и пытаюсь создать видео с хэштегом. В базе данных уже хранятся хэштеги и хэштег, который создаст пользователь (который будет добавлен при отправке видео).

Например, я добавляю более 2 хэштегов, приведенный ниже код работает для 2 случаев:

  1. Если в базе данных нет хэштега, он успешно создал и добавил все хэштеги к видео
  2. Если hashtags уже есть в БД, он успешно добавил видео
  3. Но когда в БД уже есть несколько хэштегов, а другого нет. К видео добавляется только несколько хэштегов, а не все добавленные хэштеги. Я не знаю почему. Я хочу исправить этот случай.

У меня есть 2 схемы, подобные этой:

 // Video schema
const videoSchema = new mongoose.Schema({
    url: {
        type: String
    },
    hashtag: {
        type: mongoose.Schema.Types.ObjectId,
        required: true,
        ref: 'Hashtag'
    }
})
 

и

 // Hashtag schema
const hashtagSchema = new mongoose.Schema({
    name: {
        type: String,
        required: true,
        trim: true,
    }
})
 

Пользователь разместит подобное сообщение на сервере. В этом примере Tag-In-DB-Уже находится в DB, а новый тег вводится пользователем

 {
    "url": "https://youtube.com/JvDAQD4",
    "hashtag": ["Tag-In-DB-Already", "New-Tag"]
}
 

videoObj, подобный этому

 const videoObj = new Video({
                url: data.URL,
                hashtag: []
})
 

Для проверки кода, подобного этому, мне нужно нажать ObjectId (из hashtag) в hashtagArr выше. Я проверяю каждый хэштег, если хэштега нет в БД, он будет добавлен в БД, а затем отправлен в массив. Если хэштег находится в БД, он также добавляется в массив. Я хочу, чтобы все хэштеги, отправленные пользователем, были добавлены.

 export const addHashtagToVideo = async (hashtagArr, videoObj) => {
    await hashtagArr.forEach(hashtagName => { // for each hashtag check
        Hashtag.findOne({ name: hashtagName.toLowerCase() }, (err, resp) => {
            if (err) return
            if (!resp) { // if there is no hashtag in DB
                addNewHashtagToDB(hashtagName) // run add new hashtag function
                    .then(hashtagId => { // newHashtag._id returned from below function
                        videoObj.hashtag.push({ _id: hashtagId })
                    })
            } else {
                videoObj.hashtag.push({ _id: resp._id }) // if found in DB, also pushed to video
            }
        })
    })
}

export const addNewHashtagToDB = async (hashtagName) => {
    const newHashtag = await new Hashtag({
        name: hashtagName.toLowerCase(),
    })
    newHashtag.save()
    return newHashtag._id
}
 

Спасибо за помощь

Ответ №1:

вам нужно знать, что такое возврат функции…

 export const addHashtagToVideo = async (hashtagArr, videoObj) => {
  const waitAllDone = hashtagArr.map(async tag => { // tag in hashtagArr
    const doc = await addNewHashtagToDB(tag) // find it or create it
    return doc.id
  })

  const ary = await Promise.all(waitAllDone) // [id1, id2]
  videoObj.hashtag = ary
  // return videoObj
}

export const addNewHashtagToDB = async tag => {
  const name = tag.toLowerCase()  // whatever tag is, fix it
  let doc = await Hashtag.findOne({ name }).exec() // try to find it
  if (!doc) {
    // not exist
    doc = new Hashtag({ name }) // create new doc
    await doc.save()
  }
  return doc
}
 

другая версия

 export const addHashtagToVideo = async (hashtagArr, videoObj) => {
  const waitAllDone = hashtagArr.map(addNewHashtagToDB) // amazing

  const ary = await Promise.all(waitAllDone) // [id1, id2]
  videoObj.hashtag = ary // replace it to prevent duplicat
  // return videoObj
}

export const addNewHashtagToDB = async tag => {
  const name = tag.toLowerCase()  // whatever tag is, fix it
  let doc = await Hashtag.findOne({ name }).exec() // try to find it
  if (!doc) {
    // not exist
    doc = new Hashtag({ name }) // create new doc
    await doc.save()
  }
  return doc.id // return it here
}