问题
I have following data structure:
Collection books:
{
_id: "ajafsoaifj3341",
title: "Hello World",
poems: [
{
id: "12fjenofnoi23",
addedAt: "2018-03-12...."
},
{
id: "563jdfb34jfrr",
addedAt: "2018-03-10...."
},
{
id: "78a1ewqeqweq",
addedAt: "2018-03-08...."
}
]
}
Collection poems:
{
_id: "563jdfb34jfrr",
title: "How to Join",
author: "Smith"
addedAt: "2017-12-21..."
}
I need to join these two collections to get the title of the poem. Something like:
{
_id: "ajafsoaifj3341",
title: "Hello World",
poems: {
id: "12fjenofnoi23",
addedAt: "2018-03-12....",
title: "How to Join"
}
}
I fond an example like this:
//SERVER
import { Poems } from '../imports/collections/poems';
import { Books } from '../imports/collections/books';
Meteor.publish('booksWithPoems', function (bookId) {
const book = Books.findOne({ _id: bookId });
return [
Books.find({ _id: bookId }),
Poems.find({
_id: {
$in: book.poems.id
}
})
];
});
//CLIENT
export default withTracker(props => {
const bookSubscription = Meteor.subscribe('booksWithPoems', props.editBookId);
return {
editedBook: Books.findOne({}),
editedPoems: Poems.find({}).fetch(),
bookLoaded: bookSubscription.ready()
};
})(connect(mapStateToProps, {
...
})(withRouter(BookEditor)));
But this.props.editedPoems is undefined. What is wrong here?
Maybe this are better ways to do this. I would appreciate if you could help me both with server and client code. I am quite new in Meteor/Mongo world.
And the last comment. I do not need all data from Poem documents, just "title". Thanks!
回答1:
Your publication has the following problematic part: $in
excpects an array, while book.poems.id
is a String value on a single poem. What you want, however is an array of all ids in book.poems
.
This is also the cause while the other subscription (editedBook
) receives some data and editedPoems
not. Subscription reflect only those documents, that have been found in the last execution of the publication method.
In order to get this correct you need to first map
Poems ids and set this array as value for $in
:
Meteor.publish('booksWithPoems', function (bookId) {
const book = Books.findOne({ _id: bookId });
return [
Books.find({ _id: bookId }),
Poems.find({
_id: {
$in: book.poems.map( p => p.id ), // ["12fjenofnoi23","563jdfb34jfrr","78a1ewqeqweq"]
}
})
];
});
Now it should select all poems, whose id fits one of the ids provided in the array, assigned to $in
.
I have not checked the client code and the way you join the data, but I think this mongo query selector is the main issue here.
More to read on $in: https://docs.mongodb.com/manual/reference/operator/query/in/
来源:https://stackoverflow.com/questions/49306048/create-join-of-two-collections-in-mongodb-using-meteor-js