JSdata - 查询匹配数组中的所有项(MongoDB'$ all'关键字)

时间:2017-05-16 12:31:15

标签: angularjs jsdata js-data-angular

我正在使用jsdata为Angular 1.5 Web应用程序创建本地缓存。我用相应的关系建模我的数据,每一件事情都很好。我正在讨论一个查询,我甚至不确定这是否适用于js-data:

让我们假设我有一个带有ID和名称的标签集合

 [
  {
    "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'
  }
}

当我查询帖子时,我看到我的标签出现在embedded_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 个答案:

答案 0 :(得分:0)

我在js-data _utils2.default中添加了'matchAll'函数。这适用于现在,也许是对某人的帮助。

在交叉口功能旁边添加此功能:

// 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') {
...

答案 1 :(得分:0)

'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(发现所有滤镜功能的好地方,顺便说一句)