programing

MongoError 수정 방법: 종료된 세션을 사용할 수 없습니다.

powerit 2023. 5. 13. 11:01
반응형

MongoError 수정 방법: 종료된 세션을 사용할 수 없습니다.

Node.js를 사용하여 MongoDB Atlas 컬렉션의 데이터를 읽으려고 합니다.컬렉션의 내용을 읽으려고 하면 오류가 발생합니다.MongoError: Cannot use a session that has ended여기 제 코드가 있습니다.

client.connect(err => {
    const collection = client
        .db("sample_airbnb")
        .collection("listingsAndReviews");

    const test = collection.find({}).toArray((err, result) => {
        if (err) throw err;
    });
    client.close();
});

특정 문서를 쿼리할 수 있지만 컬렉션의 모든 문서를 반환하는 방법을 잘 모르겠습니다.제가 이 오류를 검색해 봤는데, 별로 찾을 수가 없네요.감사해요.

당신의 코드에서는, 그것은 기다리지 않습니다.find()실행을 완료하고 다음 단계로 진행합니다.client.close()진술.따라서 DB에서 데이터를 읽으려고 할 때 이미 연결이 종료되었습니다.저는 이와 같은 문제에 직면하여 다음과 같이 해결했습니다.

// connect to your cluster
const client = await MongoClient.connect('yourMongoURL', { 
    useNewUrlParser: true, 
    useUnifiedTopology: true,
});
// specify the DB's name
const db = client.db('nameOfYourDB');
// execute find query
const items = await db.collection('items').find({}).toArray();
console.log(items);
// close connection
client.close();

편집: 이 모든 것은 다음과 같아야 합니다.async기능.

MongoClient를 3.3.2에서 최신 버전으로 업데이트했을 때 동일한 문제가 발생했습니다(이 글 작성 시점에서 3.5.2).패키지를 변경하여 3.3.2 버전만 설치하십시오.제이손"mongodb": "3.3.2",또는 비동기식 래퍼를 사용하여 대기합니다.

그래도 문제가 지속되면 node_modules를 제거하고 다시 설치합니다.

한 가지 옵션은 다음을 사용하는 것은Promise쇠사슬의collection.find({}).toArray()콜백 기능을 수신하거나 약속을 반환하여 통화를 연결할 수 있습니다..then()

collection.find({}).toArray() // returns the 1st promise
.then( items => {
    console.log('All items', items);
    return collection.find({ name: /^S/ }).toArray(); //return another promise
})
.then( items => {
    console.log("All items with field 'name' beginning with 'S'", items);
    client.close(); // Last promise in the chain closes the database
);

물론, 이 데이지 체인은 코드를 더 동기화시킵니다.이것은 체인의 다음 통화가 첫 번째 통화에서 사용자 ID를 얻은 다음 다음 다음 통화에서 사용자 세부 정보를 조회하는 것과 같이 이전 통화와 관련된 경우에 유용합니다.

관련이 없는 여러 쿼리를 병렬(비동기화)로 실행하고 모든 결과가 돌아오면 데이터베이스 연결을 폐기합니다.예를 들어 배열 또는 카운터의 각 호출을 추적하여 이 작업을 수행할 수 있습니다.

const totalQueries = 3;
let completedQueries = 0;

collection.find({}).toArray()
.then( items => {
    console.log('All items', items);
    dispose(); // Increments the counter and closes the connection if total reached
})

collection.find({ name: /^S/ }).toArray()
.then( items => {
    console.log("All items with field 'name' beginning with 'S'", items);
    dispose(); // Increments the counter and closes the connection if total reached
);

collection.find({ age: 55 }).toArray()
.then( items => {
    console.log("All items with field 'age' with value '55'", items);
    dispose(); // Increments the counter and closes the connection if total reached
);

function dispose(){
    if (++completedQueries >= totalQueries){
        client.close();
    }
}

3가지 질문이 있습니다.한 사람 한 사람이 호출합니다.dispose()카운터가 증가합니다.그들이 모두 호출했을 때dispose()마지막 연결도 닫힙니다.

Async/Await는 그것을 훨씬 더 쉽게 만들 것입니다. 왜냐하면 그들은 포장을 벗기기 때문입니다.Promise의 결과.then기능.

async function test(){
    const allItems = await collection.find({}).toArray();
    const namesBeginningWithS = await collection.find({ name: /^S/ }).toArray();
    const fiftyFiveYearOlds = await collection.find({ age: 55 }).toArray();
    client.close();
}

test();

다음은 비동기/Awit가 비동기 코드를 순차적으로 동작시키고 다음 비동기 함수를 호출하기 전에 하나의 비동기 함수가 완료될 때까지 기다리면서 비효율적으로 실행되는 방법을 보여주는 예입니다.

let counter = 0;

function doSomethingAsync(id, start) {
  return new Promise(resolve => {
    setTimeout(() => {
      counter++;
      const stop = new Date();    
      const runningTime = getSeconds(start, stop);
      resolve(`result${id} completed in ${runningTime} seconds`);
    }, 2000);
  });
}

function getSeconds(start, stop) {
  return (stop - start) / 1000;
}

async function test() {
  console.log('Awaiting 3 Async calls');
  console.log(`Counter before execution: ${counter}`);
  
  const start = new Date();
  
  let callStart = new Date();
  const result1 = await doSomethingAsync(1, callStart);
  
  callStart = new Date();
  const result2 = await doSomethingAsync(2, callStart);
  
  callStart = new Date();
  const result3 = await doSomethingAsync(3, callStart);
  
  const stop = new Date();

  console.log(result1, result2, result3);
  console.log(`Counter after all ran: ${counter}`);
  console.log(`Total time to run: ${getSeconds(start, stop)}`);
 }

test();

참고: 위의 예와 같이 대기하면 호출이 다시 순차적으로 수행됩니다.각각 실행하는 데 2초가 걸리는 경우 기능이 완료되는 데 6초가 걸립니다.

모든 장점을 결합하면 모든 통화를 즉시 실행하면서 비동기/Await를 사용할 수 있습니다. 다히도행.Promise이를 위한 방법이 있습니다.test()같이 쓸 수 : - 음과같쓸수있다: -

async function test(){
    let [allItems, namesBeginningWithS, fiftyFiveYearOlds] = await Promise.all([
        collection.find({}).toArray(),
        collection.find({ name: /^S/ }).toArray(),
        collection.find({ age: 55 }).toArray()
    ]);

    client.close();
}

다음은 성능의 차이를 입증하기 위한 작업 예입니다.

let counter = 0;

function doSomethingAsync(id, start) {
  return new Promise(resolve => {
    setTimeout(() => {
      counter++;
      const stop = new Date();    
      const runningTime = getSeconds(start, stop);
      resolve(`result${id} completed in ${runningTime} seconds`);
    }, 2000);
  });
}

function getSeconds(start, stop) {
  return (stop - start) / 1000;
}

async function test() {
  console.log('Awaiting 3 Async calls');
  console.log(`Counter before execution: ${counter}`);
  const start = new Date();
  
  const [result1, result2, result3] = await Promise.all([
        doSomethingAsync(1, new Date()),
        doSomethingAsync(2, new Date()),
        doSomethingAsync(3, new Date())
  ]);
  
  const stop = new Date();

  console.log(result1, result2, result3);
  console.log(`Counter after all ran: ${counter}`);
  console.log(`Total time to run: ${getSeconds(start, stop)}`);
 }

test();

다른 사람들이 이 문제에 대해 언급했지만 .toArray()가 비동기적으로 실행되므로 세션을 닫기 전에 완료되었는지 확인해야 합니다.

이것은 안 될 것입니다.

const randomUser = await db.collection('user').aggregate([ { $sample: { size: 1 } } ]);
console.log(randomUser.toArray()); 
await client.close();

이 유언장

const randomUser = await db.collection('user').aggregate([ { $sample: { size: 1 } } ]).toArray();
console.log(randomUser); 
await client.close();
client.connect(err => {
    const collection = client
        .db("sample_airbnb")
        .collection("listingsAndReviews");

    const test = collection.find({}).toArray((err, result) => {
        if (err) throw err;

        client.close();

    });        
});

언급URL : https://stackoverflow.com/questions/59816298/how-to-fix-mongoerror-cannot-use-a-session-that-has-ended

반응형