query
질의를 위해서는 먼저 BaseModel.query를 이용해 질의 객체를 만드세요. 그리고 메소드 연쇄를 통해 질의를 만들어 나간 후, Query#exec나 Query#count, Query#update, Query#delete를 사용해 질의를 실행합니다.
단순한 질의를 쉽게 실행하기 위해서 BaseModel 클래스는 Query에서 일부 메소드를 빌려와 가지고 있습니다.
const users = await User.query().where(\{ age: 27 }).exec();
// 또는
const users = await User.where(\{ age: 27 }).exec();
필터
Query#where나 Query#find를 사용해 레코드를 선택할 수 있습니다.
where
의 조건문은 MongoDB의 문법과 비슷합니다.
where
를 두개 이상 사용할 경우 논리곱(모두 참)을 의미합니다.
설명 | CORMO | SQL | MongoDB |
---|---|---|---|
같음 | User.where({ age: 27 }) | SELECT * FROM users WHERE age=27 | db.users.find({ age: 27 }) |
논리곱(모두 참) | { name: 'John Doe', age: 27 } | name='John Doe' AND age=27 | { name: 'John Doe', age: 27 } |
.where({name: 'John Doe'}).where({age: 27}) | |||
{ $and: [ { name: 'John Doe' }, { age: 27 } ] } | |||
[ { name: 'John Doe' }, { age: 27 } ] | |||
논리합(하나 이상 참) | { $or: [ { name: 'John Doe' }, { age: 27 } ] } | name='John Doe' OR age=27 | { $or: [ { name: 'John Doe' }, { age: 27 } ] } |
비교 ($lt, $gt, $lte, $gte) | [ { age: { $gt: 30 } }, { age: { $lte: 45 } } ] | age>30 AND age<=45 | { $and: [ { age: { $gt: 30 } }, { age: { $lte: 45 } } ] } |
대소문자 구분 없이 텍스트를 포함 | { name: { $contains: 'smi' } } | name LIKE '%smi%' | { name: /smi/i } |
{ name: { $contains: ['smi', 'doe'] } } | name LIKE '%smi%' OR name LIKE '%doe%' | { name: { $in: [/smi/i, /doe/i] } } | |
대소문자 구분 없이 텍스트로 시작 | { name: { $startswith: 'smi' } } | name LIKE 'smi%' | { name: /^smi/i } |
대소문자 구분 없이 텍스트로 끝남 | { name: { $endswith: 'smi' } } | name LIKE '%smi' | { name: /smi$/i } |
정규표현식 | { name: /smi/ } | name REGEXP 'smi' | { name: /smi/i } |
{ name: /smi|doe/ } | name REGEXP 'smi|doe' | { name: /smi|doe/i } | |
배열의 값 중 하나라도 일치 | { age: { $in: [ 10, 20, 30 ] } } | age IN (10,20,30) | { age: { $in: [ 10, 20, 30 ] } } |
{ age: [ 10, 20, 30 ] } | |||
부정 | { age: { $not: 27 } } | NOT (age=27) OR age IS NULL | { age: { $ne: 27 } } |
{ age: { $not: { $lt: 27 } } } | NOT (age<27) OR age IS NULL | { age: { $not: { $lt: 27 } } } | |
{ name: { $not: { $contains: 'smi' } } } | NOT (name LIKE '%smi%') OR name IS NULL | { name: { $not: /smi/i } } | |
{ name: { $not: { $contains: ['smi', 'doe'] } } } | NOT (name LIKE '%smi%' OR name LIKE '%doe%') OR name IS NULL | { name: { $nin: [/smi/i, /doe/i] } } | |
{ age: { $not: { $in: [ 10, 20, 30 ] } } } | NOT (age IN (10,20,30)) OR age IS NULL | { age: { $nin: [10,20,30] } } | |
{ age: { $not: [ 10, 20, 30 ] } } | |||
{ name: { $not: null } } | NOT name IS NULL | { age: { $ne: null } } |
식별자에 기반해 레코드를 찾으려면 하나의 ID나 ID의 배열을 인자로 하는 Query#find를 사용합니다.
논리적으로는 .where(\{ id: <주어진 ID나 ID의 배열> })
과 동일하지만, 해당 레코드가 없을 경우 find
는 예외를 발생시키는데 반해, where
는 빈 결과를 반환합니다.
조건부 활성화
하나의 질의 연쇄에서 다른 조건을 적용하고 싶은 경우, Query#if와 Query#endif를 사용할 수 있습니다. 이를 이용해 질의 문장을 단순화할 수 있습니다.
async function getOldUsers(options: \{ limit?: number; columns?: string[] }) \{
const query = User.query();
query.where(\{ age: \{ $gt: 30 } });
if (options.limit) \{
query.limit(options.limit);
}
if (options.columns) \{
query.select(options.columns as any);
}
return await query.exec();
}
// 위 코드를 다음과 같이 작성할 수 있습니다.
async function getOldUsers(options: \{ limit?: number; columns?: string[] }) \{
return await User.query()
.where(\{ age: \{ $gt: 30 } })
.if(options.limit != null)
.limit(options.limit)
.endif()
.if(options.columns != null)
.select(options.columns as any)
.endif()
.exec();
}
레코드 가져오기
Query#exec는 레코드를 가져옵니다.
보통은 Model 인스턴스의 배열을 반환합니다. 하지만 하나의 ID를 가지고 Query#find를 호출한 경우에는 하나의 Model 인스턴스를 반환합니다.
const user = await User.find(1).exec();
const users = await User.find([1, 2, 3]).exec();
Query는 내부적으로 exec
를 호출하는 then
메소드를 가지고 있습니다(즉 thenable). 따라서 exec
호출을 생략하고 단순히 await
만 붙여줘도 됩니다.
const users = await User.where(\{ age: 30 });
찾지 못하는 ID가 있는 경우 Query#find는 에러를 던집니다.
find
는 주어진 순서를 보정하지 않습니다. 순서를 보장하고 싶은 경우 대신 Query#findPreserve를 사용하십시오.
const users = await User.findPreserve([2, 1, 2, 3]).exec();
// users[0].id는 2, users[1].id는 1, users[2].id는 2, users[3].id는 3입니다.
가져오기시 몇가지 옵션을 줄 수 있습니다.
설명 | CORMO | SQL | MongoDB |
---|---|---|---|
컬럼 선택 | User.select(['id', 'name', 'age']) | SELECT id,name,age FROM users | db.users.find({}, { name: 1, age: 1 }) |
정렬 | User.order('age -name') | SELECT * FROM users ORDER BY age ASC, name DESC | db.users.find().sort({ age: 1, name: -1 }) |
제한 | User.query().limit(3) | SELECT * FROM users LIMIT 3 | db.users.find().limit(3) |
건너뛰기 | User.query().skip(3) | SELECT * FROM users LIMIT 2147483647 OFFSET 3 | db.users.find().skip(3) |
하나의 레코드만 요청하기
하나의 결과만 있는 것을 알고 있다면 (예를 들어 유니크 컬럼으로 질의), Query#one가 유용할 겁니다. 인스턴스 배열을 반환하는 대신 하나의 인스턴스 (또는 null)을 반환하도록 만듭니다.
const user = await User.where(\{ age: 27 }).one();