インクルードのインクルードにwhere句を使用してクエリを逐次化する


8

sequelizeでクエリを作成するのに苦労しています。

いくつかのコンテキスト

次のモデルがあります。

  • A Manifestationは[0..n]Event
  • Eventいずれかに属しているManifestationEventなしでは存在できませんManifestation
  • A Placeは[0..n]Event
  • Eventいずれかに属しているPlaceEventなしでは存在できませんPlace
  • A Manifestationは[1..n]Place
  • A 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すべてを取得するために、ManifestationそしてEvent与えられた中で起こってPlace。しかしEvent、それらのために、私はそれらが与えられたで起こらなくてManifestationも彼らの中に含めたいです。ManifestationPlace

以下は、私が達成しようとしている「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
      ]
    }
  ]
}

したがって、Manifestationwith id:11 を含めたいと思います。その1つがEvent指定されたPlace(with id:1)で発生するためです。

更新(20/04/06):現時点では、期待される結果を得るために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で直接それを行うことができると確信しています。アイデアや推奨事項はありますか?

ありがとう

回答:


0

これは最適ではありません。しかし、あなたはそれを試すことができます:

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);
        })
    })
}

これから、場所に割り当てられたすべてのマニフェストを取得するか、イベントを割り当てます。操作に含まれるすべてのイベントは、その場所に割り当てられます。

編集: 次のものも使用できます。

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
            })
        })
    })
}

ここでは、最初のクエリの直接的な表現のみを取り上げます。次に、含まれていない連結された症状。


あなたの答えをありがとう、それは私が実際に行うことであり、私は単純なjsの代わりにそれを行うための逐次的な方法を探していました。
xavier.seignard

ただし、db query SQLを実行できます
Nilanka Manoj

あなたの解決策を見た後、それは私が探していることもしません。私の質問をよく読んでください
xavier.seignard

申し訳ありませんが、私は今すぐ回答を編集しました
Nilanka Manoj

最初の回答にはタイプミスがあり、編集しました。また、私は新しい回答も追加しました
Nilanka Manoj
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.