Skip to content

Commit

Permalink
Merge branch 'master' into fix-386
Browse files Browse the repository at this point in the history
  • Loading branch information
StorytellerCZ authored Mar 11, 2024
2 parents cef24d0 + 899fc4e commit 203c378
Show file tree
Hide file tree
Showing 21 changed files with 1,308 additions and 119 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jobs:
runs-on: ubuntu-20.04
strategy:
matrix:
meteor: [2.3.1, 2.6.1, 2.7.3, 2.8.1, 2.9.1, 2.12]
meteor: [2.3.1, 2.6.1, 2.7.3, 2.8.1, 2.9.1, 2.12, 2.14]

steps:
- uses: actions/checkout@v3
Expand Down
56 changes: 29 additions & 27 deletions .versions
Original file line number Diff line number Diff line change
@@ -1,62 +1,64 @@
[email protected]
[email protected].1
[email protected].5
[email protected]
[email protected]
[email protected]
[email protected].1
[email protected].2
[email protected]
callback-hook@1.4.0
callback-hook@1.5.1
[email protected]
[email protected]
[email protected]
cultofcoders:grapher@1.4.1
dburles:mongo-collection-instances@0.3.5
cultofcoders:grapher@1.5.0
dburles:mongo-collection-instances@0.4.0
[email protected]
[email protected]
[email protected]
ddp-server@2.6.0
ddp-server@2.7.0
[email protected]
[email protected].2
[email protected].4
[email protected].0
[email protected].3
[email protected].8
[email protected].1
[email protected]
[email protected]
[email protected]
[email protected].2
[email protected].4
[email protected]
herteby:[email protected].6
herteby:[email protected].7
[email protected]
[email protected]
lai:collection-extensions@0.2.1_1
local-test:cultofcoders:grapher@1.4.1
[email protected].1
matb33:collection-hooks@1.1.2
meteor@1.10.3
lai:collection-extensions@0.4.0
local-test:cultofcoders:grapher@1.5.0
[email protected].3
matb33:collection-hooks@1.3.1
meteor@1.11.5
meteortesting:[email protected]
meteortesting:[email protected]
[email protected].1
[email protected].9
modules@0.19.0
[email protected].3
[email protected].10
modules@0.20.0
[email protected]
[email protected].3
[email protected].8
[email protected]
[email protected]
[email protected]
npm-mongo@4.12.1
npm-mongo@4.17.2
[email protected]
peerlibrary:[email protected]
peerlibrary:[email protected]
practicalmeteor:[email protected]
[email protected]
[email protected]
[email protected].3
[email protected].8
[email protected]
[email protected]
[email protected]
reywood:publish-composite@1.7.3
reywood:publish-composite@1.8.8
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
zodern:[email protected]
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
- Minimum Meteor version bumped to 2.3
- Update dependencies
- Allow unblocking recursive publications [@Floriferous](https://github.com/Floriferous)
- Reverse link nested objects failure [@bhunjadi](https://github.com/bhunjadi) [PR](https://github.com/cult-of-coders/grapher/pull/400)
- `reywood:publish-composite` updated to v1.8.8
- Added test for Meteor 2.12 and 2.14
- Added support for nested links in nested objects and arrays [@bhunjadi](https://github.com/bhunjadi) [PR](https://github.com/cult-of-coders/grapher/pull/479)

## 1.4.1
- Fix reactive counters when filtering on dates [@vparpoil](https://github.com/vparpoil) [PR](https://github.com/cult-of-coders/grapher/pull/402)
Expand Down
34 changes: 34 additions & 0 deletions docs/linking_collections.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,40 @@ Posts.addLinks({
You created the link, and now you can use the query illustrated above.
We decided to choose `author` as a name for our link and `authorId` the field to store it in, but it's up to you to decide this.

## Nested links

Nested links are also supported:

```js
// file: /imports/db/posts/links.js
import Posts from '...';

Posts.addLinks({
'authorObject.authorId': {
type: 'one',
collection: Meteor.users,
field: 'authorObject.authorId',
},
})
```

In this example we're assuming that `authorObject` is a nested document inside `Posts` collection, and we want to link it to `Meteor.users`.

Nested arrays are also supported, e.g.:

```js
// file: /imports/db/posts/links.js
import Posts from '...';

Posts.addLinks({
'authorsArray.authorId': {
type: 'one',
collection: Meteor.users,
field: 'authorsArray.authorId',
},
})
```

## Inversed links

Because we linked `Posts` with `Meteor.users` it means that we can also get all `posts` of an user.
Expand Down
32 changes: 19 additions & 13 deletions lib/links/lib/createSearchFilters.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,29 @@ export default function createSearchFilters(object, linker, metaFilters) {
}
}

function getIdQueryFieldStorage(object, fieldStorage, isMany = false) {
const [root, ...rest] = fieldStorage.split('.');
if (rest.length === 0) {
const ids = object[fieldStorage];
return Array.isArray(ids) ? {$in: ids} : ids;
}

const nestedPath = rest.join('.');
const rootValue = object[root];
if (Array.isArray(rootValue)) {
return {$in: _.uniq(_.union(...rootValue.map(item => dot.pick(nestedPath, item))))};
}
else if (_.isObject(rootValue)) {
return isMany ? {$in: dot.pick(nestedPath, rootValue) || []} : dot.pick(nestedPath, rootValue);
}
}

export function createOne(object, linker) {
return {
// Using {$in: []} as a workaround because foreignIdentityField which is not _id is not required to be set
// and {something: undefined} in query returns all the records.
// $in: [] ensures that nothing will be returned for this query
[linker.foreignIdentityField]: dot.pick(linker.linkStorageField, object) || {$in: []},
[linker.foreignIdentityField]: getIdQueryFieldStorage(object, linker.linkStorageField) || {$in: []},
};
}

Expand Down Expand Up @@ -69,19 +86,8 @@ export function createOneMetaVirtual(object, fieldStorage, metaFilters) {
}

export function createMany(object, linker) {
const [root, ...nested] = linker.linkStorageField.split('.');
if (nested.length > 0) {
const arr = object[root];
const ids = arr ? _.uniq(_.union(arr.map(obj => _.isObject(obj) ? dot.pick(nested.join('.'), obj) : []))) : [];
return {
[linker.foreignIdentityField]: {$in: ids}
};
}
const value = object[linker.linkStorageField];
return {
[linker.foreignIdentityField]: {
$in: _.isArray(value) ? value : (value ? [value] : []),
}
[linker.foreignIdentityField]: getIdQueryFieldStorage(object, linker.linkStorageField, true) || {$in: []},
};
}

Expand Down
20 changes: 18 additions & 2 deletions lib/query/hypernova/aggregateSearchFilters.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,24 @@
import sift from 'sift';
import dot from 'dot-object';

function getIdsFromObject(object, field) {
const parts = field.split('.');
if (parts.length === 1) {
return [dot.pick(field, object)];
}

const rootValue = object[parts[0]];
if (Array.isArray(rootValue)) {
return rootValue.map(item => dot.pick(parts.slice(1).join('.'), item));
}
else if (_.isObject(rootValue)) {
return [dot.pick(parts.slice(1).join('.'), rootValue)];
}
return [];
}

function extractIdsFromArray(array, field) {
return (array || []).map(obj => _.isObject(obj) ? dot.pick(field, obj) : undefined).filter(v => !!v);
return _.flatten((array || []).map(obj => _.isObject(obj) ? getIdsFromObject(obj, field) : [])).filter(v => !!v);
}

/**
Expand Down Expand Up @@ -44,7 +60,7 @@ export default class AggregateFilters {
createOne() {
if (!this.isVirtual) {
return {
_id: {
[this.foreignIdentityField]: {
$in: _.uniq(extractIdsFromArray(this.parentObjects, this.linkStorageField))
}
};
Expand Down
Loading

0 comments on commit 203c378

Please sign in to comment.