JSdata - запрос на совпадение всех элементов в массиве (ключевое слово MongoDB '$all')

Я использую jsdata для создания локального кэша для веб-приложения Angular 1.5. Я смоделировал свои данные с соответствующими отношениями, и все работает отлично. Я борюсь с запросом, и я даже не уверен, будет ли это вообще работать с js-данными:

Предположим, у меня есть коллекция тегов с идентификатором и именем

 [
  {
    "id": 1,
    "name": "Tag 1"
  },
  {
    "id": 2,
    "name": "Tag 2"
  }
  ,
  {
    "id": 3,
    "name": "Tag 3"
  }
]

и некоторые посты, где были назначены теги:

[   {
      "id": 1,
      "name": "Post with tags 1 and 2",
      "tags": [1, 2]
    },
    {
      "id": 2,
      "name": "Post with tags 2 and 3",
      "tags": [2,3]
    },
    {
      "id": 3,
      "name": "Post with tag 3",
      "tags": [3]
    }
]

Затем я определяю Tag и Post Datastore и устанавливаю отношение hasMany к сообщениям:

relations: {
hasMany: {
  tag: {
    localField: 'embedded_tags',
    localKeys: 'tags'
  }
}

Когда я запрашиваю сообщения, я вижу, что мои теги появляются во встроенных тегах, так что это нормально. Теперь я хотел бы отфильтровать свои посты по определенному набору тегов: допустим, я хочу видеть только посты с тегами 2 и 3, то есть пост 2.

Очевидно, это не работает

var resultISect = postDS.filter({
  where: {
    'tags': {
      'iSectNotEmpty': [1, 2]
    }
  }
})

Также это не так (и, конечно, выдает предупреждение о дублировании ключа):

var resultAnd = postDS.filter({
  where: {
    'tags': {
      'contains': 3,
      'contains': 2
    }
  }
})

В MongoDB / Mongoose есть ключевое слово $all, которое делает именно это. Есть ли способ иметь такую ​​фильтрацию в jsData или это слишком сложная задача для базы данных, и ее следует выполнять на бэкэнде - чего я хотел бы избежать, потому что это более или менее весь смысл в наличии копии локального кэша, право?

Plunkr: http://plnkr.co/edit/M44V8js0BtZaK6Xq9CYt?p=preview

2 ответа

'where' может быть массивом, это должно работать:

where: [
  {
    tags: {
      contains: 3
    }
  },
  'and'
  {
    tags: {
      contains: 2
    }
  }
]

Взяты отсюда: https://github.com/js-data/js-data/blob/c3fcde1abab910cdf4d39e3fbc42699a3b27c1da/test/unit/query/filter.test.js#L243 (хорошее место, чтобы узнать все функции фильтра, кстати)

Я добавил функцию 'matchAll' в js-data _utils2.default, Пока это работает, может быть, это кому-то поможет.

Добавьте эту функцию рядом с функцией пересечения:

// check if array contains all elements queried
function matchAll(arr, elements) {

    if (!arr || !elements) {
        return true;
    }

    for (var i = 0, length = elements.length; i < length; i++) {
        if (contains(arr, elements[i])) {
            continue;
        } else {
            return false;
        }
    }
    return true;
}

Выставьте эту функцию вместе с другими:

exports.default = {
    ...
    guid: guid,
    intersection: intersection,
    matchAll: matchAll,
    isArray: isArray,
    isBlacklisted: isBlacklisted,
    ...
}

и заставить его реагировать на новое ключевое слово:

...
} else if (op === 'isectEmpty') {
    expr = !_utils2.default.intersection(val || [], term || []).length;
} else if (op === 'isectNotEmpty') {
    expr = _utils2.default.intersection(val || [], term || []).length;
} else if (op === 'matchAll') {
    expr = _utils2.default.matchAll(val || [], term || []);
} else if (op === 'in') {
...
Другие вопросы по тегам