npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

mares-mongoose-model

v0.3.9

Published

슬로그업에���� 사용하는 node.js DDD패턴 구현 시 필요합니다. mongoose 모델 생성시 반드시 해당 모듈을 상속받아�� 합니다.

Downloads

5

Readme

mares-mongoose-model

슬로그업에서 사용하는 node.js DDD패턴 구현 시 필요합니다. mongoose 모델 생성시 반드시 해당 모듈을 상속받아야 합니다.

Installation

npm install --save mares-mongoose-model

Examples

const MaresMongooseModel = require('mares-mongoose-model')

// 다음과 같이 몽구스 모델을 상속받아 추가 함수를 구현해서 사용합니다.
class TestModel extends MaresMongooseModel {  
	/**
	 * 문자열로 몽구스 프로젝션에 필요한 필드를 정의합니다.
	 * @override
	 */
	static getAttributes() {  
		return 'id a b' 
	} 
	
	/**
	 * 다음함수는 기본 몽구스의 함수를 오버라이딩 하는 경우입니다.
	 * @override
	 * @static
	 */
	static findById() {
		//todo
	}
	
	static doSomething() {}  
}  

Action

모든 개발 패턴을 통일하기 위하여 에러핸들링, parameter 핸들링, return data의 정규화 등을 내부 지정된 함수를 이용해서 조작해야 합니다.

Mongoose error object handling

몽구스에서 나는 모든 에러는 catch 후 해당 함수를 통해서 전파해야 합니다. 내부적으로 throw를 하기 때문에 명시적으로 throw를 적을 필요가 없습니다.

class TestModel extends MaresMongooseModel {  
    static doSomething() {  
        try { 
            // call mongoose built-in method
        } catch (e) {
            this.throwRefineError(e)  
        }
    }
}  

404 error handling

데이터가 없는 경우 404에러를 throw 해줍니다.

class TestModel extends MaresMongooseModel {  
	static async doSomething() {  
		let data = await get()  
		if (data === null) {
			// 데이터가 없다면 바로 404 error를 throw한다.
			this.throwNotfoundError()
		} 
	}
}  

Parameter normalization

infra / repository 에는 domain layer의 PO가 넘어오는 경우가 많기 때문에 반드시 일반객체로 정규화 한 후 사용해야 합니다.

class TestModel extends MaresMongooseModel {  
	static async doSomething(domainObject) {
	  
		// object 인경우
		let pureObject = this.cleanObject(domainObject)
		
		// array 인경우
		let pureArray = this.cleanArray(domainObject)
	}
}  

Return mongoose object

mongoose object를 pure함수를 통해 po로 변형 후 return 해야 합니다.

class TestModel extends MaresMongooseModel {  
	static async doSomething(domainObject) {  
		let data = await get()  
		return this.toPure(data)
	}
}  

Get projection query

몽고디비의 프로젝션에 필요한 쿼리를 만들어 줍니다. 해당 함수는 내부적으로 getAttributes() 함수를 이용합니다.

class TestModel extends MaresMongooseModel {
	static getAttributes() {
		return 'id test value app.a app.b app.c.a app.c.b'  
	}
	static async doSomething(domainObject) {  
		let data = await get()  
		let projection = this.getProjection('', 'prefix') //빈문자열을 이용하면 getAttributes 함수를 이용합니다.
		/**
		 * prjection 객체는 다음과 같이 변환됩니다. 
		 * {
		 *  	'prefix.id': 1,  
		 *  	'prefix.test': 1,  
		 *  	'prefix.value': 1,  
		 *  	'prefix.app.a': 1,  
		 *  	'prefix.app.b': 1,  
		 *  	'prefix.app.c.a': 1,  
		 *  	'prefix.app.c.b': 1
		 * }
		 */
		// todo
	}
}  

Build group query

조인을 위한 쿼리를 생성하기 위한 함수를 제공합니다. 몽구스에서 조인을 하게 되면, 응답형태를 다시 객체로 만들어야 하는데 이를 자동으로 해주는 함수를 제공합니다. 아래는 order-orderItem-inventory 3개를 조인하는 예제코드 입니다. (왼쪽에서 부터 오른쪽으로 1:N 관계입니다.)

class TestModel extends MaresMongooseModel {
	static async findFullOrder(appKey, order, orderItem = null) {
		// 최초 모든 프로젝션 값을 얻어옵니다.
		const orderItemAttr = mongoose.models.OrderItem.getAttributes()  
		const inventoryAttr = mongoose.models.Inventory.getAttributes()  
		const orderAttr = this.getAttributes()  
		
		// 쿼리작성을 시작합니다.
		let aggregateQuery = []
		
		// 먼저 appKey라는 필드를 검색합니다.
		aggregateQuery.push({  
            $match: {  
                appKey  
            }  
		})
		
		// join을 합니다. $lookup 키워드를 이용합니다.
		// from은 N관계의 join할 컬렉션명입니다.
		// foreignField는 OrderItem에서 들고있는 외래키의 이름입니다.
		// localField는 order의 고유키입니다. (primary Key)
		// as는 해당 N관계의 값들이 포함될 필드명입니다. 아래 배열로 들어갑니다.
		aggregateQuery.push({  
            $lookup: {  
                from: 'OrderItem',  
                foreignField: 'order',  
                localField: '_id',  
                as: 'orderItems'  
            }  
		})
		
		// unwind를 하게 되면 orderItems안의 배열의 값들이 모두 펼쳐지면서 각각의 로우로 변경됩니다. orderItems를 들고 있는 객체의 모든 필드는 중복됩니다.
		aggregateQuery.push({$unwind: '$orderItems'})  
		
		aggregateQuery.push({  
            $match: {  
                'orderItems.canceledAt': {$exists: false},  
            }  
		})  
		
		aggregateQuery.push({  
            $lookup: {  
                from: 'Inventory',  
                foreignField: 'orderItem',  
                localField: 'orderItems._id',  
                as: 'orderItems.inventories'  
            }
		})  
		aggregateQuery.push({$unwind: '$orderItems.inventories'})  
		aggregateQuery.push({  
            $match: {  
                'orderItems.inventories.canceledAt': {$exists: false}  
            }  
		})  
		aggregateQuery.push({$limit: 1})

		// buildGroupQuery를 이용하여 실제로 그룹핑을 위한 쿼리를 만듭니다.
		// 앞에 문자열은 root collection명을 제외한 depth 구조입니다. 닷(점)으로 구분합니다. 또한 최종 lookup 구문의 as와 동일합니다.
		// 두번째 인자는 프로젝션 스트링 값입니다. 만일 위에 depth의 닷이 1개라면 총 3개의 프로젝션 값이 필요합니다.
		aggregateQuery = [...aggregateQuery, ...this.buildGroupQuery('orderItems.inventories', [orderAttr, orderItemAttr, inventoryAttr])]  
		try {  
            let orders = await this.aggregate(aggregateQuery)  
            if (!orders || orders.length === 0) this.throwNotfoundError()  
            return this.toPure(orders[0])  
		} catch (e) {  
            this.throwRefineError(e)  
		}  
	}
}

Remove null fields

클라이언트에서 생성시(POST) 생성할 필드가 없을때 null을 보낼 수 있는데 이때 null 값을 모두 제거하여 생성시 $set의 필드에 null이 들어가는 것을 방지하기 위한 함수 입니다.

class TestModel extends MaresMongooseModel {
	static async doSomething(domainObject) {  
		// obj의 null값을 제거해줍니다.
		// 만일 모든 sub object 혹은 sub array의 값이 모두 null이면 해당 객체나 배열은 단순 null로 바뀝니다.
		// 두번째 인자는 undefined or {}, []값을 없애줄지 여부 입니다.
		this.removeNullFields(obj, true)
	}
}  

Generate unset query

값을 수정할 때 null을 보내면 해당 필드를 unset으로 제거하여 주고 싶을 때 사용합니다.

class TestModel extends MaresMongooseModel {
	static async doSomething(domainObject) {  
		// null 값을 찾아서 unset 쿼리를 만들어 줍니다.
		// 두번째 인자는 unset 쿼리 객체를 만들 때 배열의 원소까지 체크할지 여부입니다. 만일 true 라면 'array.0.a' 와같은 형태로 만들어 주며, false일 경우에는 해당 array 키값을 무시합니다.
		this.toUnsetFromNullFields(obj, true)
	}
}