sql - 在包含的包含上使用 where 子句对查询进行 Sequelize

标签 sql node.js sequelize.js

我正在努力使用 sequelize 创建查询。

一些上下文

我有以下型号:

  • 一个 Manifestation可以有 [0..n] Event
  • Event属于一个 Manifestation (没有 Event 就不能存在 Manifestation)
  • 一个 Place可以有 [0..n] Event
  • Event属于一个 Place (没有 Event 就不能存在 Place)
  • 一个 Manifestation可以有 [1..n] Place
  • 一个 Place可以有 [0..n] Manifestation

  • 我将关系建模如下:

    Manifestation.hasMany(Event, { onDelete: 'CASCADE', hooks: true })
    Event.belongsTo(Manifestation)
    
    Place.hasMany(Event, { onDelete: 'CASCADE', hooks: true })
    Event.belongsTo(Place)
    
    Manifestation.belongsToMany(Place, { through: 'manifestation_place' })
    Place.belongsToMany(Manifestation, { through: 'manifestation_place' })
    

    对我来说,这似乎相当正确,但如果您有意见,请不要犹豫。

    问题

    我正在尝试查询 Place为了得到所有ManifestationEvent发生在给定的 Place .但是对于Event的,我想将它们包含在他们的 Manifestation 中即使Manifestation在给定的 Place 中不会发生.

    下面是我试图实现的“JSON”结构:
    {
      id: 1,
      name: "Place Name",
      address: "Place address",
      latitude: 47.00000,
      longitude: -1.540000,
      manifestations: [
        {
          id: 10,
          title: "Manifestation one",
          placeId: 1,
          events: []
        },
        {
          id: 11,
          title: "Manifestation two",
          placeId: 3,
          events: [
            id: 5,
            title: "3333",
            manifestationId: 11,
            placeId: 1
          ]
        }
      ]
    }
    

    所以我想包括 Manifestationid : 11, 因为它的一个 Event发生在给定的 Place (与 id :1)

    更新 (04/06/20):现在我依靠 javascript 来获得预期的结果

    我想如果我在询问之前发布我当前的解决方案会很好。
    router.get('/test', async (req, res) => {
      try {
        const placesPromise = place.findAll()
        const manifestationsPromise = manifestation.findAll({
          include: [
            { model: event },
            {
              model: place,
              attributes: ['id'],
            },
          ],
        })
    
        const [places, untransformedManifestations] = await Promise.all([
          placesPromise,
          manifestationsPromise,
        ])
    
        const manifestations = untransformedManifestations.map(m => {
          const values = m.toJSON()
          const places = values.places.map(p => p.id)
          return { ...values, places }
        })
    
        const result = places
          .map(p => {
            const values = p.toJSON()
            const relatedManifestations = manifestations
              .filter(m => {
                const eventsPlaceId = m.events.map(e => e.placeId)
                return (
                  m.places.includes(values.id) ||
                  eventsPlaceId.includes(values.id)
                )
              })
              .map(m => {
                const filteredEvents = m.events.filter(
                  e => e.placeId === values.id
                )
                return { ...m, events: filteredEvents }
              })
            return { ...values, manifestations: relatedManifestations }
          })
          .filter(p => p.manifestations.length)
    
        return res.status(200).json(result)
      } catch (err) {
        console.log(err)
        return res.status(500).send()
      }
    })
    

    但我很确定我可以直接用 sequelize 做到这一点。任何想法或建议?

    谢谢

    最佳答案

    这不是最佳的。但是你可以试试:

    const findPlace = (id) => {
        return new Promise(resolve => {
            db.Place.findOne({
                where: {
                    id: id
                }
            }).then(place => {
                db.Manefestation.findAll({
                    include: [{
                        model: db.Event,
                        where: {
                            placeId: id
                        }
                    }]
    
                }).then(manifestations => {
                    const out = Object.assign({}, {
                        id: place.id,
                        name: place.name,
                        address: place.address,
                        latitude: place.latitude,
                        longitude: place.longitude,
                        manifestations: manifestations.reduce((res, manifestation) => {
                            if (manifestation.placeId === place.id || manifestation.Event.length > 0) {
                                res.push({
                                    id: manifestation.id,
                                    title: manifestation.id,
                                    placeId: manifestation.placeId,
                                    events: manifestation.Event
                                })
                            }
                            return res;
                        }, [])
                    })
                })
                resolve(out);
            })
        })
    }
    

    从中,您将获得分配给地点或具有任何分配事件的所有表现形式。所有包含在 manefestations 中的事件都被分配到这个地方。

    编辑:
    您也可以使用以下方法:
    const findPlace = (id) => {
        return new Promise(resolve => {
            db.Place.findOne({
                include: [{
                    model: db.Manefestation,
                    include: [{
                        model: db.Event,
                        where: {
                            placeId: id
                        }
                    }]
    
                }],
                where: {
                    id: id
                }
            }).then(place => {
                db.Manefestation.findAll({
                    include: [{
                        model: db.Event,
                        where: {
                            placeId: id
                        }
                    }],
                    where: {
                        placeId: {
                            $not: id
                        }
                    }
    
                }).then(manifestations => {
                    place.Manefestation = place.Manefestation.concat(manifestations.filter(m=>m.Event.length>0))
                    resolve(place);// or you can rename, reassign keys here
                })
            })
        })
    }
    

    这里我只取第一个查询中的直接表现。然后,不包括和连接的表现形式。

    关于sql - 在包含的包含上使用 where 子句对查询进行 Sequelize,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60863743/

    相关文章:

    javascript - Electron 的本地存储未在动态创建的元素上保存我的点击事件

    javascript - Nodejs中如何区分文本文件和json文件

    node.js - Sails JS 模型 Rest API

    php - 平均查询的总轮数

    php - mysql,使用 "where"中的条件

    sql - 在带有输入参数的存储过程中使用 LIKE

    sql - 外键可以为 NULL 和/或重复吗?

    sequelize.js - 如何在 Sequelize 中建立自引用的多对多关联?

    node.js - 在同构 Redux 应用程序中,保持 API 调用较小还是一次性发送所有信息是更好的做法吗?

    javascript - Sequelize - 批量插入排除任何已经存在的条目