1

I have this api route

import { Client } from "@elastic/elasticsearch";
import { NextResponse } from "next/server";

export async function GET(request) {
  try {
    const client = new Client({ node: "http://localhost:9200" });

    const { body } = await client.search({
      index: "game-of-thrones",
      size: 100,
      body: {
        query: {
          match_all: {}
        }
      }
    });

    const hits = body.hits?.hits || [];
    const documents = hits.map((hit) => hit._source);

    return NextResponse.json(documents, { status: 200 });
  } catch (error) {
    console.error("Elasticsearch Error:", error);
    return NextResponse.error();
  }
}

and this client side page

'use client';
import { useEffect, useState } from 'react';

export default function Home() {
  const [documents, setDocuments] = useState([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch('/api/all');
        const data = await response.json();
        setDocuments(data);
        setLoading(false);
      } catch (error) {
        console.error('Error fetching documents:', error);
      }
    };

    fetchData();
  }, []);

  return (
    <main>
      {loading ? (
        <p>Loading...</p>
      ) : (
        <div>
          {documents.map((document) => (
            <div key={document._id}>
              <h2>{document.character}</h2>
              <p>{document.quote}</p>
            </div>
          ))}
        </div>
      )}
    </main>
  );
}

I am trying to read from an existing index but i keep getting this error

Elasticsearch Error: TypeError: Cannot read properties of undefined (reading 'hits')
    at GET (webpack-internal:///(sc_server)/./src/app/api/all/route.js:24:27)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async eval (webpack-internal:///(sc_server)/./node_modules/next/dist/server/future/route-modules/app-route/module.js:244:37)
- error RangeError [ERR_HTTP_INVALID_STATUS_CODE]: Invalid status code: 0
    at new NodeError (node:internal/errors:399:5)
    at ServerResponse.writeHead (node:_http_server:344:11)
    at ServerResponse.writeHead (c:\admin\node_modules\next\dist\compiled\compression\index.js:46:263)
    at ServerResponse._implicitHeader (node:_http_server:335:8)
    at ServerResponse.end (c:\admin\node_modules\next\dist\compiled\compression\index.js:22:749)
    at sendResponse (c:\admin\node_modules\next\dist\server\send-response.js:49:30)
    at doRender (c:\admin\node_modules\next\dist\server\base-server.js:970:62)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async cacheEntry.responseCache.get.incrementalCache.incrementalCache (c:\admin\node_modules\next\dist\server\base-server.js:1162:28)
    at async c:\admin\node_modules\next\dist\server\response-cache\index.js:99:36 {
  code: 'ERR_HTTP_INVALID_STATUS_CODE'
}

My index looks like this

{"took":3,"timed_out":false,"_shards":{"total":1,"successful":1,"skipped":0,"failed":0},"hits":{"total":{"value":25,"relation":"eq"},"max_score":1.0,"hits":[{"_index":"game-of-thrones","_id":"XHsmMIgBAA3lxqgqah3Y","_score":1.0,"_source":{"character":"Ned Stark","quote":"Winter is coming."}},{"_index":"game-of-thrones","_id":"W3smMIgBAA3lxqgqaR0g","_score":1.0,"_source":{"character":"Ned Stark","quote":"Winter is coming."}},{"_index":"game-of-thrones","_id":"XXsmMIgBAA3lxqgqbB1T","_score":1.0,"_source":{"character":"Daenerys Targaryen","quote":"I am the blood of the dragon."}},{"_index":"game-of-thrones","_id":"XnsmMIgBAA3lxqgqbB3p","_score":1.0,"_source":{"character":"Tyrion Lannister","quote":"A mind needs books like a sword needs a whetstone."}},{"_index":"game-of-thrones","_id":"X3smMIgBAA3lxqgq7h3K","_score":1.0,"_source":{"character":"Ned Stark","quote":"Winter is coming."}},{"_index":"game-of-thrones","_id":"YHsmMIgBAA3lxqgq7x0h","_score":1.0,"_source":{"character":"Daenerys Targaryen","quote":"I am the blood of the dragon."}},{"_index":"game-of-thrones","_id":"YXsmMIgBAA3lxqgq7x2O","_score":1.0,"_source":{"character":"Tyrion Lannister","quote":"A mind needs books like a sword needs a whetstone."}},{"_index":"game-of-thrones","_id":"YnsmMIgBAA3lxqgq8R3R","_score":1.0,"_source":{"character":"Ned Stark","quote":"Winter is coming."}},{"_index":"game-of-thrones","_id":"Y3smMIgBAA3lxqgq8h0i","_score":1.0,"_source":{"character":"Daenerys Targaryen","quote":"I am the blood of the dragon."}},{"_index":"game-of-thrones","_id":"ZHsmMIgBAA3lxqgq8h12","_score":1.0,"_source":{"character":"Tyrion Lannister","quote":"A mind needs books like a sword needs a whetstone."}}]}}

How can i return the documents that i want?

1 Answer 1

1

I have managed to fix it this way

Server

import { Client } from "@elastic/elasticsearch";
import { NextResponse } from "next/server";

export async function GET(request) {
  try {
    const client = new Client({ node: "http://localhost:9200" });

    const { body } = await client.search({
      index: "game-of-thrones",
      query: {
        match_all: {}
      }
    }, { meta: true });

    console.log('body', body);

    return NextResponse.json(body, { status: 200 });
  } catch (error) {
    console.error("Elasticsearch Error:", error);
    return NextResponse.error();
  }
}

Client

'use client';
import { useEffect, useState } from 'react';

export default function Home() {
  const [documents, setDocuments] = useState([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch('/api/all');
        const data = await response.json();
        setDocuments(data.hits.hits.map((hit) => hit._source));
        setLoading(false);
      } catch (error) {
        console.error('Error fetching documents:', error);
      }
    };

    fetchData();
  }, []);

  return (
    <main>
      {loading ? (
        <p>Loading...</p>
      ) : (
        <div>
          {documents.map((document, index) => (
            <div key={index}>
              <h2>{document.character}</h2>
              <p>{document.quote}</p>
            </div>
          ))}
        </div>
      )}
    </main>
  );
}
Sign up to request clarification or add additional context in comments.

1 Comment

So the solution was to move the data.hits.hits.map((hit) => hit._source) from the server to the client ? Why did that work?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.