Skip to main content

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>