Make the MongoDB docs better! We value your opinion. Share your feedback for a chance to win $100.
Click here >
Docs Menu
Docs Home
/ /

연결 동작 사용자 지정

Mongoid의 연관 관계를 사용하면 모델 간의 관계를 생성할 수 있습니다. 이 가이드 에서는 Mongoid를 사용하여 애플리케이션 에서 연결이 작동하는 방식을 사용자 지정하는 방법을 학습 수 있습니다. 다음 섹션에서는 연결 동작을 사용자 지정하는 방법을 설명합니다.

확장을 사용하면 연관 관계에 사용자 정의 기능을 추가할 수 있습니다. 다음 예시 와 같이 연결 정의에 차단 지정하여 연결에 대한 확장을 정의할 수 있습니다.

class Band
include Mongoid::Document
embeds_many :albums do
def find_by_name(name)
where(name: name).first
end
end
end
band.albums.find_by_name("Omega") # returns album "Omega"

class_name 매크로를 사용하여 연결에 대한 사용자 지정 클래스 이름을 지정할 수 있습니다. 이는 연관 관계의 이름을 클래스 이름이 아닌 다른 이름으로 지정할 때 유용합니다. 다음 예시 class_name 매크로를 사용하여 records 이라는 포함된 연관 관계가 Album 클래스를 나타내도록 지정합니다:

class Band
include Mongoid::Document
embeds_many :records, class_name: "Album"
end

기본값 으로 Mongoid는 연관 관계를 조회할 때 상위 클래스의 _id 필드 사용합니다. primary_keyforeign_key 매크로를 사용하여 사용할 다른 필드를 지정할 수 있습니다. 다음 예시 Band 클래스의 albums 연결에 대한 새 프라이머리 키와 외래 키를 지정합니다.

class Band
include Mongoid::Document
field :band_id, type: String
has_many :albums, primary_key: 'band_id', foreign_key: 'band_id_ref'
end
class Album
include Mongoid::Document
field :band_id_ref, type: String
belongs_to :band, primary_key: 'band_id', foreign_key: 'band_id_ref'
end

has_and_belongs_to_many 연결을 지정하는 경우 inverse_primary_keyinverse_foreign_key 매크로를 사용할 수도 있습니다. inverse_primary_key 매크로는 원격 모델이 문서를 조회하는 데 사용하는 로컬 모델의 필드 를 지정합니다. inverse_foreign_key 매크로는 inverse_primary_key에서 찾은 값을 저장하는 원격 모델의 필드 를 지정합니다.

다음 예시 has_and_belongs_to_many 연관 관계의 BandMembers 클래스에 대한 새 프라이머리 및 외래 키를 지정합니다.

class Band
include Mongoid::Document
field :band_id, type: String
field :member_ids, type: Array
has_many :members,
primary_key: 'member_id', foreign_key: 'member_ids',
inverse_primary_key: 'band_id', inverse_foreign_key: 'band_ids'
end
class Member
include Mongoid::Document
field :member_id, type: String
field :band_ids, type: Array
has_many :bands,
primary_key: 'band_id', foreign_key: 'band_ids',
inverse_primary_key: 'member_id', inverse_foreign_key: 'member_ids'
end

scope 매개 변수를 사용하여 연결 범위를 지정할 수 있습니다. scope 매개변수는 Mongoid가 연관 관계의 일부로 간주하는 문서를 결정합니다. 범위 지정 연결은 쿼리 시 범위 조건과 일치하는 문서만 반환합니다. scope 를 아리티가 0인 Proc 또는 관련 모델의 명명된 범위를 참조하는 Symbol 로 설정하다 수 있습니다. 다음 예시 Band 클래스의 연결에 대한 사용자 지정 범위를 설정합니다.

class Band
include Mongoid::Document
has_many :albums, scope: -> { where(published: true) }
# Uses a scope called "upcoming" on the Tour model
has_many :tours, scope: :upcoming
end

참고

범위 조건과 일치하지 않는 문서를 연결에 추가할 수 있습니다. Mongoid는 문서를 데이터베이스 에 저장하고 관련 메모리에 표시됩니다. 그러나 연결을 쿼리할 때는 문서가 표시되지 않습니다.

Mongoid는 연관 관계를 메모리에 로드할 때, 기본값 으로 validates_associated 매크로를 사용하여 하위 항목도 있는지 확인합니다. Mongoid는 다음 연결 유형에 대해 하위 항목의 유효성을 검사합니다.

  • embeds_many

  • embeds_one

  • has_many

  • has_one

  • has_and_belongs_to_many

다음 예시 와 같이 연결을 정의할 때 validate 매크로를 false 로 설정하여 이 유효성 검사 동작을 해제할 수 있습니다.

class Band
include Mongoid::Document
embeds_many :albums, validate: false
end

Mongoid는 일대일 및 일대다 연관 관계의 하위 클래스에 대한 다형성을 지원합니다. 다형성 연결을 사용하면 단일 연결에 서로 다른 클래스 유형의 객체가 포함될 수 있습니다. 하위 연결에서 polymorphic 옵션을 true 로 설정하고 상위 연결에 as 옵션을 추가하여 다형성 연결을 정의할 수 있습니다. 다음 예시 Band 클래스에 다형성 연관을 생성합니다.

class Tour
include Mongoid::Document
has_one :band, as: :featured
end
class Label
include Mongoid::Document
has_one :band, as: :featured
end
class Band
include Mongoid::Document
belongs_to :featured, polymorphic: true
end

앞의 예시 에서 Band 클래스의 :featured 연관 관계는 Label 또는 Album 문서 포함할 수 있습니다.

중요

Mongoid는 자식에서 부모로의 다형성만 지원합니다. 상위 has_one 또는 has_many 연관 관계를 다형성으로 지정할 수 없습니다.

has_and_belongs_to_many 다형성을 지원하지 않는 연관 관계들입니다.

버전 9.0.2부터 Mongoid는 글로벌 레지스트리를 통해 사용자 지정 다형성 유형을 지원합니다. 다른 클래스를 나타내는 대체 키를 지정하여 데이터에서 코드를 분리할 수 있습니다. 다음 예시 문자열 "artist"Band 클래스의 대체 키로 지정합니다.

class Band
include Mongoid::Document
identify_as 'artist'
has_many :albums, as: :record
end

앞의 예시 에서 identify_as 지시문은 Mongoid가 Band 클래스를 데이터베이스 에 "artist" 문자열로 저장 하도록 지시합니다.

다음 예시 와 같이 여러 개의 별칭을 지정할 수도 있습니다.

class Band
include Mongoid::Document
identify_as 'artist', 'group', 'troupe'
has_many :albums, as: :record
end

앞의 예시 에서 artist 이 기본값 이름이고 다른 이름은 레코드 조회에만 사용됩니다. 이를 통해 데이터의 연결을 끊지 않고 코드를 리팩터링할 수 있습니다.

다형성 유형 별칭은 전역적입니다. 지정하는 키는 전체 코드베이스에서 고유해야 합니다. 그러나 모델의 다양한 하위 집합에 사용할 수 있는 대체 리졸버를 등록할 수 있습니다. 이 경우 키는 각 해석기에 대해서만 고유해야 합니다. 다음 예시 대체 리졸버를 등록하는 방법을 보여줍니다.

Mongoid::ModelResolver.register_resolver Mongoid::ModelResolver.new, :mus
Mongoid::ModelResolver.register_resolver Mongoid::ModelResolver.new, :tool
module Music
class Band
include Mongoid::Document
identify_as 'bnd', resolver: :mus
end
end
module Tools
class Band
include Mongoid::Document
identify_as 'bnd', resolver: :tool
end
end

Music::BandTools::Band 모두 "bnd"(으)로 별칭이 지정되어 있지만 각 모델은 충돌을 피하기 위해 자체 리졸버를 사용합니다.

참조된 연관 관계에 dependent 옵션을 제공하여 문서 삭제될 때 Mongoid가 관련 문서를 처리하는 방법을 지정할 수 있습니다. 다음 옵션을 지정할 수 있습니다.

  • delete_all: 모델 콜백을 실행 하지 않고 모든 하위 문서를 삭제합니다.

  • destroy: 하위 문서를 삭제하고 모든 모델 콜백을 실행합니다.

  • nullify: 하위 문서의 외래 키를 nil로 설정합니다. 하위 문서 상위 문서만 참조하는 경우 고아가 될 수 있습니다.

  • restrict_with_exception: 하위 문서 비어 있지 않으면 예외가 발생합니다.

  • restrict_with_error: 하위 문서 비어 있지 않으면 작업을 취소하고 false 를 반환합니다.

dependent 옵션을 지정하지 않으면 Mongoid는 상위 문서 삭제될 때 하위 문서 변경하지 않은 상태로 둡니다. 하위 문서 삭제된 상위 문서 계속 참조하며, 상위 문서를 통해서만 참조되는 경우 하위 문서 고아가 됩니다.

다음 예시 Band 클래스에 dependent 옵션을 지정합니다.

class Band
include Mongoid::Document
has_many :albums, dependent: :delete_all
belongs_to :label, dependent: :nullify
end

기본값 으로 Mongoid는 상위 문서 저장할 때 포함되지 않은 연관 관계의 관련 문서를 자동으로 저장하지 않습니다. 이로 인해 존재하지 않는 문서에 대한 dangling 참조가 발생할 수 있습니다.

참조된 연관 관계에서 autosave 옵션을 사용하면 상위 문서 저장할 때 연관된 문서를 자동으로 저장할 수 있습니다. 다음 예시 연결된 Album 클래스가 있는 Band 클래스를 만들고 autosave 옵션을 지정합니다.

class Band
include Mongoid::Document
has_many :albums
end
class Album
include Mongoid::Document
belongs_to :band, autosave: true
end
band = Band.new
album = Album.create!(band: band)
# The band is persisted at this point.

참고

Mongoid는 accepts_nested_attributes_for 옵션을 사용하는 연관 관계에 자동 저장 기능을 자동으로 추가합니다.

Mongoid는 내장된 문서를 상위 문서 에 저장하므로 내장된 연관 관계에 대해서는 autosave 옵션을 지정할 필요가 없습니다.

has_oneembeds_one와 같은 일대일 연결에 autobuild 옵션을 추가하여 nil 연결에 액세스할 때 새 문서 자동으로 인스턴스화할 수 있습니다. 다음 예시 Band 클래스의 연관 관계에 autobuild 옵션을 추가합니다:

class Band
include Mongoid::Document
embeds_one :label, autobuild: true
has_one :producer, autobuild: true
end

Mongoid가 문서 터치하면 문서의 updated_at 필드 현재 날짜 및 시간으로 업데이트합니다. 모든 belongs_to 연관 관계에 touch 옵션을 추가하여 하위 문서 업데이트될 때마다 Mongoid가 상위 문서 접촉하도록 할 수 있습니다. 다음 예시 Band 클래스의 연관 관계에 touch 옵션을 추가합니다:

class Band
include Mongoid::Document
field :name
belongs_to :label, touch: true
end

touch 옵션을 사용하여 상위 연관 관계의 다른 필드 문자열이나 기호로 지정할 수도 있습니다. Mongoid가 상위 연관 관계를 건드릴 때, updated_at 필드 와 지정된 필드 모두 현재 날짜 및 시간으로 설정합니다.

다음 예시 Mongoid에게 bands_updated_at 필드 터치하도록 지시합니다.

class Band
include Mongoid::Document
belongs_to :label, touch: :bands_updated_at
end

참고

포함된 연관 관계에서, 내장된 문서 가 터치될 때, Mongoid는 그 부모들을 재귀적으로 터치합니다. 이 때문에 embedded_in 연관 관계에 touch 속성을 추가할 필요가 없습니다.

Mongoid는 embedded_in 연관 관계에서 터치할 추가 필드를 지정하는 지원 하지 않습니다.

연결된 필드 에 속하는 객체 수를 저장 하려면 counter_cache 옵션을 사용합니다. 이 옵션을 지정하면 Mongoid는 연결된 상위 모델에 카운터 필드 저장합니다.

counter_cache 옵션은 카운터 필드 이름에 다음 두 값 중 하나를 허용합니다.

  • true: Mongoid는 연관 관계의 이름을 기반으로 기본값 카운터 필드 이름을 사용합니다. 예시 들어 연결이 Band인 경우 기본값 카운터 필드 이름은 bands_count입니다.

  • string 또는 symbol: Mongoid는 해당 값을 카운터 필드 이름으로 직접 사용합니다.

다음 방법 중 하나를 사용하여 카운터 캐시 에 대한 컨테이너 제공할 수 있습니다.

  • 상위 모델에서 명시적 카운터 필드 정의합니다.

  • 상위 모델에 Mongoid::Attributes::Dynamic 모듈을 포함하면 Mongoid가 처음 사용할 때 카운터 필드 동적으로 생성할 수 있습니다.

명시적 카운터 필드

이 접근 방식에서는 상위 모델에서 직접 카운터 필드 선언합니다. 이는 고정된 스키마 와 명시적 필드 유형이 필요한 경우에 유용합니다.

다음 예시 Label 클래스에서 명시적 bands_count 필드 선언하고 기본값 카운터 필드 이름을 사용합니다.

class Band
include Mongoid::Document
# Uses the default counter field name: bands_count
belongs_to :label, counter_cache: true
end
class Label
include Mongoid::Document
field :bands_count, type: Integer
has_many :bands
end

counter_cache 옵션에 문자열을 전달하여 사용자 지정 카운터 필드 이름을 지정할 수도 있습니다.

class Band
include Mongoid::Document
belongs_to :label, counter_cache: :active_bands_count
end
class Label
include Mongoid::Document
field :active_bands_count, type: Integer
has_many :bands
end

동적 카운터 필드

상위 모델에 Mongoid::Attributes::Dynamic 모듈을 포함하면 Mongoid는 런타임 중에 카운터 필드 동적으로 생성하고 업데이트 할 수 있습니다. 이는 유연한 스키마 필요하고 카운터 필드 명시적으로 선언하지 않으려는 경우에 유용합니다.

다음 예시 Mongoid::Attributes::Dynamic 를 사용하여 Mongoid가 Label 클래스에서 카운터 필드 동적으로 생성할 수 있도록 허용합니다.

class Band
include Mongoid::Document
belongs_to:label, counter_cache: true
end
class Label
include Mongoid::Document
include Mongoid::Attributes::Dynamic
has_many :bands
end

Mongoid::Attributes::Dynamic 모듈을 사용할 때 Mongoid는 명시적인 필드 필드 선언할 때와 필드 명명 규칙을 카운터 *_count 필드 에 counter_cache 사용합니다. 기본값 필드 이름은 연결을 기반으로 하며, 옵션의 string으로 사용자 지정 필드 이름을 지정하지 않는 한.

돌아가기

내장된 연관 관계

이 페이지의 내용