목록을 표시하는 간단한 앱 설정이 Projects있습니다. autopublish클라이언트에게 모든 것을 보내지 않도록 패키지를 제거했습니다 .
<template name="projectsIndex">
{{#each projects}}
{{name}}
{{/each}}
</template>
autopublish이 켜져 있으면 모든 프로젝트가 표시됩니다.
if Meteor.isClient
Template.projectsIndex.projects = Projects.find()
제거하면 추가로 다음을 수행해야합니다.
if Meteor.isServer
Meteor.publish "projects", ->
Projects.find()
if Meteor.isClient
Meteor.subscribe "projects"
Template.projectsIndex.projects = Projects.find()
그렇다면 클라이언트 측 find()방법은 서버 측에서 게시 된 레코드 만 검색 한다고 말하는 것이 정확 합니까? find()한 번만 전화해야 할 것 같았 기 때문에 나를 괴롭 혔습니다 .
답변
컬렉션, 간행물 및 구독은 Meteor의 까다로운 영역으로, 문서에서 더 자세히 논의 할 수있어 잦은 혼동 을 피할 수 있습니다. 종종 혼동 되는 용어로 인해 증폭됩니다 .
다음은 Sacha Greif ( DiscoverMeteor의 공동 저자 )가 발행물과 구독을 하나의 슬라이드로 설명합니다.
find()두 번 이상 호출해야하는 이유를 올바르게 이해하려면 Meteor에서 컬렉션, 출판 및 구독이 작동하는 방식을 이해해야합니다.
-
MongoDB에서 컬렉션을 정의합니다. 아직 Meteor가 관련되지 않았습니다. 이 컬렉션은 포함 된 데이터베이스 레코드가 (또한 몽고 모두에 의해 “문서”라는 및 유성 하지만, “문서는”데이터베이스 레코드보다 더 일반적이며, 예를 들어, 업데이트 사양 또는 쿼리 선택이 문서입니다 도 – 자바 스크립트가 포함 된 객체
field: value쌍). -
그런 다음 Meteor 서버에서 다음을 사용하여 컬렉션 을 정의 합니다 .
MyCollection = new Mongo.Collection('collection-name-in-mongo')이러한 컬렉션에는 MongoDB 컬렉션의 모든 데이터가 포함되어 있으며
MyCollection.find({...})이를 실행 하면 커서 가 반환됩니다 (레코드 집합,이를 반복하고 반환하는 메서드 포함). -
이 커서는 (대부분의 경우) 레코드 집합 ( “레코드 집합” 이라고 함) 을 게시 (전송)하는 데 사용됩니다 . 선택적 으로 해당 레코드의 일부 필드 만 게시 할 수 있습니다 . 이 기록 세트 (입니다 하지 클라이언트가 있다고 컬렉션) 가입 에. 게시는 새 클라이언트가 구독 할 때마다 호출되고 반환 할 레코드를 관리하기위한 매개 변수를 사용할 수 있는 게시 함수에 의해 수행됩니다 (예 : 해당 사용자의 문서 만 반환하는 사용자 ID).
-
클라이언트에서 , 당신은 Minimongo의 컬렉션을 부분적으로 반영 일부 서버에서 기록을. “부분적으로”당신이 일반적으로 페이지로드 속도를 높이기 위해,가 필요한 레코드 만 클라이언트에 보낼 및 만이 필요하기 때문에 그들이 “기록의 일부를”일부 필드 포함하고 수 있기 때문에 과 에 권한이 접속하다.
Minimongo는 본질적으로 순수 JavaScript에서 Mongo의 비 영구적 인 메모리 내 구현입니다. 이 클라이언트가 작업하는 데이터베이스의 하위 집합 만 저장하는 로컬 캐시 역할을합니다. 클라이언트 (find)에 대한 쿼리는 서버와 통신하지 않고이 캐시에서 직접 제공됩니다.
이러한 Minimongo 컬렉션은 처음에는 비어 있습니다. 그들은
Meteor.subscribe('record-set-name')전화. 구독 할 매개 변수 는 컬렉션 이름이 아닙니다. 서버가 호출에 사용한 레코드 세트 의 이름입니다
publish. 이subscribe()호출은 클라이언트를 레코드 세트 (예 : 가장 최근의 블로그 게시물 100 개)에있는 레코드의 하위 집합으로, 각 레코드의 필드 전체 또는 하위 집합 (예 :title및date)에 구독합니다 . Minimongo는 들어오는 레코드를 어떤 컬렉션에 저장할지 어떻게 알 수 있습니까? 컬렉션의 이름은collection게시 처리기의added,changed및removed콜백에 사용되는 인수가 되거나 누락 된 경우 (대부분의 경우) 서버에있는 MongoDB 컬렉션의 이름이됩니다.
레코드 수정
이것이 Meteor가 매우 편리하게 만드는 곳입니다. 클라이언트의 Minimongo 컬렉션에서 레코드 (문서)를 수정할 때 Meteor는 이에 의존하는 모든 템플릿을 즉시 업데이트하고 변경 사항을 서버로 다시 보냅니다. MongoDB에 변경 사항을 저장하고 해당 문서를 포함한 레코드 세트를 구독 한 적절한 클라이언트로 전송합니다. 이를 지연 보상 이라고 하며 Meteor 의 7 가지 핵심 원칙 중 하나입니다 .
여러 구독
다른 레코드를 가져 오는 여러 구독을 가질 수 있지만 _id. 이것은 명확하게 설명되지 않지만 Meteor 문서에 암시되어 있습니다.
레코드 세트를 구독하면 서버에 레코드를 클라이언트로 보내도록 지시합니다. 와 동일한 이름을 가진 클라이언트를 저장 지역 Minimongo 컬렉션에서이 기록
collection에 사용되는 인수는 핸들러의 게시added,changed및removed콜백. Meteor는 클라이언트에서 일치하는 컬렉션 이름으로 Mongo.Collection을 선언 할 때까지 들어오는 속성을 큐에 넣습니다.
어떤 설명되지 것은 당신이 때 발생하는 것입니다 하지 않습니다 명시 적으로 사용 added, changed그리고 removed대부분의 시간이다 -, 또는 전혀 핸들러를 게시 할 수 있습니다. 이 가장 일반적인 경우 컬렉션 인수는 1 단계에서 서버에서 선언 한 MongoDB 컬렉션의 이름에서 가져옵니다. 레코드는 클라이언트의 동일한 컬렉션에 저장됩니다. 의 수준까지 최고 수준의 필드 에 문서를 나란히하고 클라이언트에서 클라이언트 작업 측에 다른 최상위 필드를 발송 기능을 게시 – 유성 구독이 겹칠 수 있도록 문서 사이에 일련의 조합을 수행 할을 담당 컬렉션은두 필드 집합의 합집합 .
예 : 클라이언트에서 동일한 컬렉션을 채우는 여러 구독
다른 작업을 수행하더라도 서버와 클라이언트 모두에서 동일한 방식으로 선언하는 BlogPosts 컬렉션이 있습니다.
BlogPosts = new Mongo.Collection('posts');
클라이언트 BlogPosts에서 다음에서 레코드를 가져올 수 있습니다.
-
최근 10 개의 블로그 게시물 구독
// server Meteor.publish('posts-recent', function publishFunction() { return BlogPosts.find({}, {sort: {date: -1}, limit: 10}); } // client Meteor.subscribe('posts-recent'); -
현재 사용자의 게시물 구독
// server Meteor.publish('posts-current-user', function publishFunction() { return BlogPosts.find({author: this.userId}, {sort: {date: -1}, limit: 10}); // this.userId is provided by Meteor - http://docs.meteor.com/#publish_userId } Meteor.publish('posts-by-user', function publishFunction(who) { return BlogPosts.find({authorId: who._id}, {sort: {date: -1}, limit: 10}); } // client Meteor.subscribe('posts-current-user'); Meteor.subscribe('posts-by-user', someUser); -
가장 인기있는 게시물 구독
- 기타
이 모든 문서 는 서버 posts의 BlogPosts컬렉션을 통해 MongoDB 의 컬렉션에서 가져와 BlogPosts클라이언트 의 컬렉션으로 끝납니다 .
이제 find()두 번 이상 호출해야하는 이유를 이해할 수 있습니다 . 두 번째는 모든 구독의 문서가 동일한 컬렉션에 있고 관심있는 문서 만 가져와야하기 때문입니다. 예를 들어 클라이언트에서 가장 최근 게시물을 가져 오려면 서버에서 쿼리를 미러링하면됩니다.
var recentPosts = BlogPosts.find({}, {sort: {date: -1}, limit: 10});
이렇게하면 클라이언트가 지금까지받은 모든 문서 / 레코드, 상위 게시물과 사용자 게시물 모두에 커서가 반환됩니다. ( Geoffrey에게 감사드립니다 ).
답변
예, 클라이언트 측 find ()는 Minimongo의 클라이언트에있는 문서 만 반환합니다. 에서 문서 :
클라이언트에서 Minimongo 인스턴스가 생성됩니다. Minimongo는 본질적으로 순수 JavaScript에서 Mongo의 비 영구적 인 메모리 내 구현입니다. 이 클라이언트가 작업하는 데이터베이스의 하위 집합 만 저장하는 로컬 캐시 역할을합니다. 클라이언트 (find)에 대한 쿼리는 서버와 통신하지 않고이 캐시에서 직접 제공됩니다.
당신이 말했듯이, publish ()는 클라이언트가 가질 문서를 지정합니다.
답변
기본 엄지 손가락의 규칙은 여기 publish와 subscribed변수 이름은 클라이언트와 서버 측에서 동일해야합니다.
Mongo DB와 클라이언트 측의 컬렉션 이름은 동일해야합니다.
내 컬렉션에 대해 게시 및 구독을 사용하고 있다고 가정하면 employees코드는 다음과 같습니다.
서버 측
여기서 var키워드 사용 은 선택 사항입니다 (이 파일에 컬렉션을 로컬로 만들려면이 키워드를 사용하십시오).
CollectionNameOnServerSide = new Mongo.Collection('employees');
Meteor.publish('employeesPubSub', function() {
return CollectionNameOnServerSide.find({});
});
클라이언트 측 .js 파일
CollectionNameOnClientSide = new Mongo.Collection('employees');
var employeesData = Meteor.subscribe('employeesPubSub');
Template.templateName.helpers({
'subcribedDataNotAvailable' : function(){
return !employeesData.ready();
},
'employeeNumbers' : () =>{
CollectionNameOnClientSide.find({'empId':1});
}
});
클라이언트 측 .html 파일
여기에서 subcribedDataNotAvailable헬퍼 메서드를 사용 하여 클라이언트 측에서 데이터가 준비되었는지 확인하고, 데이터가 준비되면 employeeNumbers헬퍼 메서드를 사용하여 직원 번호를 인쇄 할 수 있습니다 .
<TEMPLATE name="templateName">
{{#if subcribedDataNotAvailable}}
<h1> data loading ... </h1>
{{else}}
{{#each employeeNumbers }}
{{this}}
{{/each}}
{{/if}}
<TEMPLATE>
답변
// on the server
Meteor.publish('posts', function() {
return Posts.find();
});
// on the client
Meteor.subscribe('posts');