Comments (4)
Sure.
The idea, in summary, is to publish all the meetings and people in those meetings (memberships), and also related data (location of the meeting, people in the meeting, roles, etc).
I didn't reduce the code to avoid you thinking this could be done in a different way due to lack of details. Of course, you can find better ways to do it and I'll be glad to try 😉
export function meetingsRelatedCursors(
meetingsCursor,
{ communityId, personId: currentPersonId, accountId }
) {
const {
labelsIds: labelsIdsWithDuplicates,
meetingsIds: meetingsIdsWithDuplicates,
locationsIds: locationsIdsWithDuplicates,
} = meetingsCursor.fetch().reduce(
(acc, meeting) => ({
labelsIds: [...acc.labelsIds, ...(meeting.labelsIds || [])],
meetingsIds: [...acc.meetingsIds, meeting._id],
locationsIds: [...acc.locationsIds, meeting.locationId],
}),
{
labelsIds: [],
meetingsIds: [],
locationsIds: [],
}
);
const labelsIds = [...new Set(labelsIdsWithDuplicates)];
const meetingsIds = [...new Set(meetingsIdsWithDuplicates)];
const locationsIds = [...new Set(locationsIdsWithDuplicates)];
const locationsCursor = Locations.find({
_id: { $in: locationsIds },
});
const labelsCursor = Labels.find({ _id: { $in: labelsIds } });
const labelSetsIds = labelsCursor.map(({ labelSetId }) => labelSetId);
const labelSetsCursor = LabelSets.find({ _id: { $in: labelSetsIds } });
const defaultRolesCursor = MeetingRoles.findBy('community', {
communityId,
isDefault: false,
});
const defaultRolesIds = defaultRolesCursor.map(({ _id }) => _id);
const $or = [
currentPersonId && { personId: currentPersonId },
{ rolesIds: { $in: defaultRolesIds } },
].filter(Boolean);
this.autorun(() => {
const meetingMembershipsCursor = MeetingMemberships.find({
meetingId: { $in: meetingsIds },
$or,
});
const {
peopleIds: peopleIdsWithDuplicates,
rolesIds: rolesIdsWithDuplicates,
} = meetingMembershipsCursor.fetch().reduce(
(acc, membership) => ({
peopleIds: [...acc.peopleIds, membership.personId],
rolesIds: [...acc.rolesIds, ...(membership.rolesIds || [])],
}),
{
peopleIds: [],
rolesIds: [],
}
);
const peopleIds = [...new Set(peopleIdsWithDuplicates)];
const rolesIds = [...new Set(rolesIdsWithDuplicates)];
const peopleCursor = People.find(
{
accountId,
_id: { $in: peopleIds },
},
{ fields: { _id: 1 } }
);
const profilesCursor = PeopleProfiles.find(
{
communityId,
personId: { $in: peopleIds },
},
{
fields: {
communityId: 1,
firstName: 1,
lastName: 1,
companyName: 1,
personId: 1,
title: 1,
photoId: 1,
},
}
);
const imagesIds = profilesCursor
.map(({ photoId }) => photoId)
.filter(Boolean);
const imagesCursor = Images.find(
{
communityId,
_id: { $in: imagesIds },
},
{
fields: {
url: 1,
},
}
);
const rolesCursor = MeetingRoles.find({
_id: { $in: rolesIds },
});
return [
meetingMembershipsCursor,
peopleCursor,
profilesCursor,
imagesCursor,
rolesCursor,
];
});
return [meetingsCursor, labelsCursor, labelSetsCursor, locationsCursor];
}
Meteor.publish(
'meetings/meetings#appBySearch',
securedScope(
currentPersonScope(function appBySearch(terms) {
this.autorun(() => {
const meetingsCursor = Meetings.findBy('search', terms);
return meetingsRelatedCursors.call(this, meetingsCursor, terms);
});
})
)
);
Then before the meetings are in the client my code already receives the ready
message. Later in the next tracker reaction, the meetings are available but the problem is that I show for a few milliseconds "No meetings available" for the user. I can delay this message but the time to delay will depend on the internet speed from the client then, for now, I'm not using two autoruns.
The problem that I was solving with these nested autoruns is to avoid querying the Meetings collection very often as it does not change too much, but Memberships collection changes all the time when people interact with our app then it's important to be in a separated autorun block.
Also, see that meetingsRelatedCursors
is used by other publications.
findBy
is our homemade find that applies some transformations in the terms of the query, in the end, it will return a regular collection find()
from meteor-reactive-publish.
Hmm. Maybe first provide a short example/test?
from meteor-reactive-publish.
Sorry. I was writing my PhD thesis so I was away for a bit.
Yes, I think the problem is that code currently marks whole publish as ready when the ready
is called the first time from wherever. And for internal autoruns that happens once all returned cursors are published for the first time. But I do not see in your code where you are publishing anything more after those cursors. So ready
should still happen only after [meetingsCursor, labelsCursor, labelSetsCursor, locationsCursor]
are published for the first time.
I suggest you create a simple test case and add it to tests, which should be currently failing because of the behavior you are noticing. Keep it as simple as possible.
from meteor-reactive-publish.
Thanks, we will work on that.
from meteor-reactive-publish.
Related Issues (20)
- Probably we should not be doing handles.push(result) if handles is a computation
- After updating to Meteor 1.4.4.1 ReactiveVar is not defined HOT 14
- Multiple cursors for collection HOT 6
- Make sure DDP._CurrentPublicationInvocation is correctly set during autorun reruns HOT 1
- Update to latest server-autorun dependency HOT 3
- Error on Meteor Update 1.6.1 when using practicalmeteor:mocha HOT 48
- Re-using observers HOT 8
- it doesn't work with meteor 1.6.1 ? HOT 6
- Is reactive-publish expected to work with this.changed on a "virtual" collection? HOT 14
- Stopping subscription before it's ready can leave observers running forever HOT 2
- Question: How to publish to specific client side collection? HOT 2
- [Meteor 1.8.1] data not removed from client due to ddp-server internal changes HOT 12
- Question: Meteor 1.8.1 - ReferenceError: ReactiveVar is not defined HOT 4
- Update peerlibrary:reactive-mongo dependency to @0.3.0 HOT 3
- Memory leak server crash with (0.3.0) HOT 2
- Issue with using observeChanges in autorun function HOT 4
- Update observing query changes patching
- The package overrides or ignores my Mongo poolSize setting HOT 1
- ReferenceError: ReactiveVar is not defined HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from meteor-reactive-publish.