Population
There are no joins in RxDB but sometimes we still want references to documents in other collections. This is where population comes in. You can specify a relation from one RxDocument to another RxDocument in the same or another RxCollection of the same database. Then you can get the referenced document with the population-getter.
This works exactly like population with mongoose.
Schema with ref​
The ref
-keyword in properties describes to which collection the field-value belongs to (has a relationship).
export const refHuman = {
title: 'human related to other human',
version: 0,
primaryKey: 'name',
properties: {
name: {
type: 'string'
},
bestFriend: {
ref: 'human', // refers to collection human
type: 'string' // ref-values must always be string or ['string','null'] (primary of foreign RxDocument)
}
}
};
You can also have a one-to-many reference by using a string-array.
export const schemaWithOneToManyReference = {
version: 0,
primaryKey: 'name',
type: 'object',
properties: {
name: {
type: 'string'
},
friends: {
type: 'array',
ref: 'human',
items: {
type: 'string'
}
}
}
};
populate()​
via method​
To get the referred RxDocument, you can use the populate()-method. It takes the field-path as attribute and returns a Promise which resolves to the foreign document or null if not found.
await humansCollection.insert({
name: 'Alice',
bestFriend: 'Carol'
});
await humansCollection.insert({
name: 'Bob',
bestFriend: 'Alice'
});
const doc = await humansCollection.findOne('Bob').exec();
const bestFriend = await doc.populate('bestFriend');
console.dir(bestFriend); //> RxDocument[Alice]
via getter​
You can also get the populated RxDocument with the direct getter. Therefore you have to add an underscore suffix _
to the fieldname.
This works also on nested values.
await humansCollection.insert({
name: 'Alice',
bestFriend: 'Carol'
});
await humansCollection.insert({
name: 'Bob',
bestFriend: 'Alice'
});
const doc = await humansCollection.findOne('Bob').exec();
const bestFriend = await doc.bestFriend_; // notice the underscore_
console.dir(bestFriend); //> RxDocument[Alice]
Example with nested reference​
const myCollection = await myDatabase.addCollections({
human: {
schema: {
version: 0,
type: 'object',
properties: {
name: {
type: 'string'
},
family: {
type: 'object',
properties: {
mother: {
type: 'string',
ref: 'human'
}
}
}
}
}
}
});
const mother = await myDocument.family.mother_;
console.dir(mother); //> RxDocument
Example with array​
const myCollection = await myDatabase.addCollections({
human: {
schema: {
version: 0,
type: 'object',
properties: {
name: {
type: 'string'
},
friends: {
type: 'array',
ref: 'human',
items: {
type: 'string'
}
}
}
}
}
});
//[insert other humans here]
await myCollection.insert({
name: 'Alice',
friends: [
'Bob',
'Carol',
'Dave'
]
});
const doc = await humansCollection.findOne('Alice').exec();
const friends = await myDocument.friends_;
console.dir(friends); //> Array.<RxDocument>