简体   繁体   English

如何在 MongoDB 和 NodeJS 中正确使用 $lookup

[英]How to use $lookup correctly in MongoDB and NodeJS

I would like to use the $lookup operator in MongoDB to pull data from two collections where, for this example, the name fields match.我想使用 MongoDB 中的 $lookup 运算符从两个集合中提取数据,在本例中,名称字段匹配。 I have used MongoDB Compass to verify the lookup code and it works, and then used the 'Export to Node' feature to get the query, but I'm getting an error (below).我已经使用 MongoDB Compass 来验证查找代码并且它可以工作,然后使用“导出到节点”功能来获取查询,但是我收到了一个错误(如下)。

This is my query (API endpoint)这是我的查询(API 端点)

import { connectToDatabase } from "util/mongodb"
export default async (req, res) => {

const pipeline = [
    {
        '$lookup' : {
            'from' : "addresses",
            'localField' : "name",
            'foreignField' : "name",
            'as' : "addresses"
        }
    }
]

const { db } = await connectToDatabase()
const posts = await db.collection('users').aggregate(pipeline);
res.json(posts)
console.log(res)

EDIT: I'm unsure whether I should be using db.collection or db.getCollection.编辑:我不确定我是否应该使用 db.collection 或 db.getCollection。 If I use db.collection in Robo3T (Mongo GUI) it responds with 'db.collection is not a function' but works with 'db.getCollection'.如果我在 Robo3T(Mongo GUI)中使用 db.collection,它会响应“db.collection 不是函数”,但可以与“db.getCollection”一起使用。 If I use 'db.getCollection' in Node it then says 'db.getCollection is not a function'.如果我在 Node 中使用“db.getCollection”,那么它会说“db.getCollection 不是函数”。

The above query is called like this:上面的查询是这样调用的:

const fetcher = url => axios.get(url).then(res => res.data)

export default function Read() {

    const { data, error } = useSWR('/api/getData', fetcher)
    if (error) return `An error has occurred: ${error}`;
    if (!data) return "Loading...";

    return (
        <>
            ...
            {data.map((post) => (
                ...
            ))}
            ...
        </>
    )
}

When I open the above page I get the following error:当我打开上述页面时,出现以下错误:

TypeError [ERR_INVALID_ARG_TYPE]: The first argument must be of type string or an instance of Buffer, ArrayBuffer, or Array or an Array-like Object. Received an instance of Object
at Function.from (buffer.js:333:9)
at toBuffer (/Users/Matt/Documents/WebApps/project/next-mongo-crud/node_modules/next/dist/compiled/compression/index.js:1:143155)
at ServerResponse.write (/Users/Matt/Documents/WebApps/project/next-mongo-crud/node_modules/next/dist/compiled/compression/index.js:1:141329)
at AggregationCursor.ondata (_stream_readable.js:719:22)
at AggregationCursor.emit (events.js:315:20)
at addChunk (_stream_readable.js:309:12)
at readableAddChunk (_stream_readable.js:284:9)
at AggregationCursor.Readable.push (_stream_readable.js:223:10)
at /Users/Matt/Documents/WebApps/project/next-mongo-crud/node_modules/mongodb/lib/core/cursor.js:372:12
at handleCallback (/Users/Matt/Documents/WebApps/project/next-mongo-crud/node_modules/mongodb/lib/core/cursor.js:32:5) {
code: 'ERR_INVALID_ARG_TYPE'

EDIT 2: I have a working query where data is fetched from just one collection, I just need to get the $lookup query to work.编辑 2:我有一个工作查询,其中仅从一个集合中获取数据,我只需要让 $lookup 查询工作即可。 Here's the single collection query:这是单个集合查询:

import { connectToDatabase } from "util/mongodb"
export default async (req, res) => {
const { db } = await connectToDatabase()
const posts = await db
    .collection("users")
    .find({})
    .toArray();
res.json(posts);
}

Can anyone see what is causing the error, please?任何人都可以看到导致错误的原因吗? I have looked through the corresponding answers in SO but I can't find a solution.我已经查看了 SO 中的相应答案,但找不到解决方案。

Cheers, Matt干杯,马特

when I looked at your front end, it gets posts and error.当我查看您的前端时,它会收到帖子和错误信息。

but the back end it returns posts, it would need to return both values as a json但是后端它返回帖子,它需要将两个值作为 json 返回

import { connectToDatabase } from "util/mongodb"

export default async (req, res) => {
  try {
    const pipeline = [
      {
        '$lookup' : {
            'from' : 'addresses',
            'localField' : 'name',
            'foreignField' : 'name',
            'as' : 'addresses'
        }
      }
    ]

    const { db } = await connectToDatabase()
    const posts = await db.collection('users').aggregate(pipeline).toArray();
    return res.json({ ...posts })
  } catch (error) {
    return res.json({ error })
  }
} // -> in your example, the closing of the function was missing.

I'm relying on your example as I can't reproduce your code locally I really can't.我依赖你的例子,因为我无法在本地重现你的代码,我真的不能。 but I think this can already give you a hand.但我认为这已经可以帮到你了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM