简体   繁体   中英

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

This is my query (API endpoint)

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. If I use db.collection in Robo3T (Mongo GUI) it responds with 'db.collection is not a function' but works with 'db.getCollection'. If I use 'db.getCollection' in Node it then says 'db.getCollection is not a function'.

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. 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.

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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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