PHPackages                             bnomei/kirby-mongodb - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. bnomei/kirby-mongodb

ActiveKirby-plugin[Database &amp; ORM](/categories/database)

bnomei/kirby-mongodb
====================

Khulan is a cache driver and content cache with NoSQL interface for Kirby using MongoDB

1.4.5(1y ago)29[1 issues](https://github.com/bnomei/kirby-mongodb/issues)MITPHPPHP &gt;=8.2.0

Since Jul 1Pushed 1y ago2 watchersCompare

[ Source](https://github.com/bnomei/kirby-mongodb)[ Packagist](https://packagist.org/packages/bnomei/kirby-mongodb)[ RSS](/packages/bnomei-kirby-mongodb/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (10)Dependencies (7)Versions (14)Used By (0)

🐎 Khulan - Kirby MongoDB
========================

[](#-khulan---kirby-mongodb)

[![Release](https://camo.githubusercontent.com/aba2178cc83e6f89c5b5244fc480c0087a6ebe9bcbcbc09c607268918ecc4530/68747470733a2f2f666c61742e62616467656e2e6e65742f7061636b61676973742f762f626e6f6d65692f6b697262792d6d6f6e676f64623f636f6c6f723d6165383166662669636f6e3d676974687562266c6162656c)](https://camo.githubusercontent.com/aba2178cc83e6f89c5b5244fc480c0087a6ebe9bcbcbc09c607268918ecc4530/68747470733a2f2f666c61742e62616467656e2e6e65742f7061636b61676973742f762f626e6f6d65692f6b697262792d6d6f6e676f64623f636f6c6f723d6165383166662669636f6e3d676974687562266c6162656c)[![Discord](https://camo.githubusercontent.com/36eaef1b06f4996feb7587aa3281dcbd658e57535bc6b5e10110ed108e7a7a03/68747470733a2f2f666c61742e62616467656e2e6e65742f62616467652f646973636f72642f626e6f6d65693f636f6c6f723d3732383964612669636f6e3d646973636f7264266c6162656c)](https://discordapp.com/users/bnomei)[![Buymecoffee](https://camo.githubusercontent.com/62e55d1129b82bf9c2fd4656451e81ab87a9787e7c9676ca58276532ed9666ee/68747470733a2f2f666c61742e62616467656e2e6e65742f62616467652f69636f6e2f646f6e6174653f69636f6e3d6275796d6561636f6666656526636f6c6f723d464638313346266c6162656c)](https://www.buymeacoffee.com/bnomei)

Khulan is a cache driver and content cache with NoSQL interface for Kirby using MongoDB.

Installation
------------

[](#installation)

- unzip [master.zip](https://github.com/bnomei/kirby-mongodb/archive/master.zip) as folder `site/plugins/kirby-mongodb`or
- `git submodule add https://github.com/bnomei/kirby-mongodb.git site/plugins/kirby-mongodb` or
- `composer require bnomei/kirby-mongodb`

MongoDB
-------

[](#mongodb)

There are various ways to install [MongoDB](https://www.mongodb.com/). This is one way to do it on localhost for Mac OSX using Homebrew and MongoDB Atlas.

```
brew install mongodb-atlas
atlas setup # create account and sign-in
atlas deployments setup # -> select localhost
atlas deployments start # start the local mongodb
```

Usecase
-------

[](#usecase)

The plugin caches all content files and keeps the cache up to date when you add/remove or update content. This cache will be used when constructing page/file/user objects making everything that involves model faster (even the Panel).

It will also allow you to query the content cache directly as a NoSQL database which might be very useful for some use-cases like filtering or searching content.

Setup
-----

[](#setup)

For each template you want to be cached you need to use a model to add the content cache logic using a trait.

**site/models/default.php**

```
class DefaultPage extends \Kirby\Cms\Page
{
    use \Bnomei\ModelWithKhulan;
}
```

Note

You can also use the trait for user models. File models are patched automatically.

Kirby's Content goes NoSQL
--------------------------

[](#kirbys-content-goes-nosql)

The plugin writes the content cache to a collection named `khulan` in the database. You can query this collection directly. It is **not** wrapped in an Cache object. This allows you to treat all your Kirby content as a NoSQL database.

```
// using the collection
$document = khulan()->find(['uuid' => 'XXX']);

// find a single page by uuid string
$page = khulan((string) $myIdOrUUID);

// find a single page by uuid by field-key
$page = khulan(['uuid' => 'page://betterharder']);

// find all pages with a template
$pages = khulan(['template' => 'post']);

// find a user by email or Id
$user = khulan($emailOrId);

// find a file by filename and template
$file = khulan(['filename' => 'my-image.jpg', 'template' => 'image']);
```

### Special Fields with \[\], {} and \[,\]

[](#special-fields-with---and-)

The plugin creates modified copies of a few field types to make the YAML based content from Kirby ready for queries. You can use

- `fieldname[]` to query for a value in an array from pages/files/user fields and
- `fieldname{}` to query for an objectId in an array from pages/files/user fields and
- `fieldname[,]` to query for fields in comma separated strings like tags/select/radio/checkbox/multiselect fields.

```
// find all pages that have another page linked
$pages = khulan([
    'related[]' => ['$in' => ['page://fasterstronger']],
]);
$pages = khulan([
    'related{}' => ['$in' => ['dc9f7835c2400cc4']], // objectId
]);

// find all products in the category 'books' or 'movies'
// that had been modified within the last 7 days
$pages = khulan([
    'template' => 'product',
    'category[,]' => ['$in' => ['books', 'movies']],
    'modified' => ['$gt' => time() - (7 * 24 * 60 * 60)]
]);
```

### Example: Filtering and Resolving Relations

[](#example-filtering-and-resolving-relations)

With Kirby's content cache as a NoSQL database you can do some advanced filtering. If you would do the same with Kirby's filtering on collection you would end up loading a lot pages and that is not as efficient. We can load the information we need directly from the cache without the need to load the full page object.

Why would we bother to read the content from a NoSQL based cache and not just put a cache around the native Kirby logic? Because the hard thing with caches is to know when to invalidate them. With the content cache we can query the NoSQL based cache directly and updating any model will be reflected instantly. Whereas with a cache around the native Kirby logic we would need rebuild the cache on every change (like with the [pages cache](https://getkirby.com/docs/guide/cache#caching-pages)).

Let's assume we have two models: `film` and `actor`. The `film` model has a field `actors` which is a pages field with linked `actor` pages. We want to list all films with their actors.

#### Load 1000 films and their actors, total of 6429 pages accessed in 250ms

[](#load-1000-films-and-their-actors-total-of-6429-pages-accessed-in-250ms)

```
$films = page('films')->children();
foreach ($films as $film) {
    echo $film->title();
    $actors = [];
    foreach ($film->actors()->toPages() as $actor) {
        $actors[] = $actor->title();
    }
    echo implode(', ', $actors);
}
```

#### Query the cache instead to get the same information in under 100ms

[](#query-the-cache-instead-to-get-the-same-information-in-under-100ms)

```
/** @var \MongoDB\Driver\Cursor $films */
$films = khulan()->aggregate([
    [
        // only get pages with template 'film'
        '$match' => ['template' => 'film'],
    ],
    [
        // lookup actors by their mongodb objectId
        // this will create an array of objects
        '$lookup' => [
            'from' => 'kirby',
            'localField' => 'actors{}',
            'foreignField' => '_id',
            'as' => 'actor_details',
        ],
    ],
    [
        // only get the fields we need
        // to make the query even faster
        '$project' => [
            'title' => 1,
            'id' => 1,
            'actor_details.title' => 1,
        ],
    ],
]);

/** @var \MongoDB\BSON\Document $film */
foreach ($films as $film) { ?>
