【问题标题】:underscore.js - create array of unique items from objects embedded in a list of objectsunderscore.js - 从嵌入在对象列表中的对象创建唯一项数组
【发布时间】:2015-12-27 14:31:33
【问题描述】:

我一直在尝试在我正在处理的Meteor 项目中使用underscore.js,但似乎无法弄清楚如何转换一组对象。

这些对象看起来像这样(大约有 15k,但它们看起来都像这两个):

 [{
   "_id": "a_0011223344",
   "taggedUsers": [{
     "id": 1122244453,
     "username": "john123"
   }],
   "field": "ABC"
 }, {
   "_id": "a_0011223345",
   "taggedUsers": [{
     "id": 1122244454,
     "username": "bill123"
   }, {
     "id": 1122244455,
     "username": "jim123"
   }],
   "field": "ABC"
 }]

每个对象可以有一个或多个"taggedUsers" 对象,我需要一个唯一的"taggedUsers.username" 字段列表。 Meteor 不支持 mongoDB 的 distinct 函数,所以我尝试使用 underscore.js 代替(根据我读过的内容和this post 中的推荐)。

在我的服务器端控制台 db.myCollection.distinct("taggedUsers.username") 返回所需的结果 ["john123", "bill123", "jim123"],但我无法在 underscore.js 中复制它。

我一直在尝试_.each_.map_.pluck_.uniq 的组合,但没有成功。我认为它可能与嵌入对象中的字段有关,但不确定。

理想情况下,我想返回一个如下所示的对象数组:

[{
  "id": 1122244453,
  "username": "john123",
  "field": "ABC"
}, {
  "id": 1122244454,
  "username": "bill123",
  "field": "ABC"
}, {
  "id": 1122244455,
  "username": "jim123",
  "field": "DEF"
}]
只删除了taggedUsers.usernametaggedUsers.idfield 字段,并删除了所有重复项,但如果我也能像在db.colleciton.distinct() 函数中一样获得taggedUsers.usernames 的数组,我会很高兴。

最终知道如何获取基本数组、唯一对象数组(或者甚至可能如何在模板帮助程序中获取db.collection.distinct() 的结果)会很好,但是任何帮助或要点正确的方向将不胜感激!

【问题讨论】:

  • 您想要一个标记用户数组,但该示例显示您还有一个field: ABC。是不是打错字了?
  • 父对象中的“字段”也会有帮助,让我编辑问题以使其更清楚@DavidWeldon
  • @DavidWeldon 您是否建议尝试查找 underscore.js 解决方案,或者我应该尝试在服务器上运行 mongo 查询并使用方法调用它?
  • 这取决于 - 您是否将文档发布给客户端只是为了执行此操作,还是出于其他原因需要在客户端上使用它们?如果它们已经发布,在帮助程序中使用下划线会更快。
  • @DavidWeldon 因为有这么多我每次只发布 20-30 个模板。鉴于此,我可能应该在服务器上运行它,但出于教育目的,如果你能用下划线告诉我如何做到这一点,那就太棒了!谢谢

标签: javascript arrays mongodb meteor underscore.js


【解决方案1】:

根据我们的谈话,听起来最好通过方法调用在服务器上计算它。出于教育目的,以下是使用下划线的方法:

// Get an array of docs somehow
var docs = Collection.find().fetch();

var taggedUsers = _.chain(docs)
  .map(function(d) {
    // Copy the 'field' to each of the tagged users within a doc
    _.each(d.taggedUsers, function(user) {
      user.field = d.field;
    });
    return d;
  })
  .pluck('taggedUsers') // Extract only the tagged users arrays
  .flatten() // Flatten them into a single array
  .value();

// taggedUsers could look something like:
// [ { id: 1122244453, username: 'john123', field: 'ABC' },
//   { id: 1122244454, username: 'bill123', field: 'ABC' },
//   { id: 1122244455, username: 'jim123', field: 'ABC' },
//   { id: 1122244453, username: 'john123', field: 'ABC' } ]

// Compute a unique lists of tagged users, where the docs are unique by id
var utu = _.uniq(taggedUsers, false, function(user) {return user.id;});

【讨论】:

  • 谢谢,这似乎是带下划线的正确方法,但我的控制台将taggedUsersutu 作为空数组返回。我的查询如下所示:Collection.find({"taggedUsers": {"$exists": true}}, {fields: { _id: 1, field: 1, "taggedUsers.username": 1, "taggedUsers.id": 1}}).fetch(); 如果有帮助。我认为该错误与 "taggedUsers.id""taggedUsers.username" 周围的引号有关,但可能是错误的。
  • 确保docs 里面有东西。我用您提供的示例测试了代码并且它有效。也许试试var docs = Collection.find({taggedUsers: {$exists: true}}).fetch()。 (假设 Collection 替换为您的实际集合名称)。
  • 看起来像这样:imgur.com/55tYWnz。显然不要认为您的解决方案不起作用,但不确定我缺少什么。 .field 应该是 field 字段(即 ABC、DEF),还是获取 userd 值的一种方式?另外,d 应该代表什么?谢谢!
  • ddocs 数组中的单个文档。 usertaggedUsers 数组的单个元素。如果你console.log(docs[0]),你会得到什么?也许您的结构与示例中使用的结构不同。你有我可以看到的测试回购吗?我需要跑步,但我过会再检查一下。
  • 这里是控制台中[0]对象的打印输出,在蒙古语中:imgur.com/NeMzFhW。会继续努力,但很高兴你回到我身边!我以前读过你的博客,所以在这里遇到你很酷,谢谢你的帮助。
猜你喜欢
  • 2020-01-25
  • 1970-01-01
  • 2021-11-21
  • 2020-12-21
  • 2012-05-12
  • 1970-01-01
  • 1970-01-01
  • 2019-10-06
  • 2011-10-25
相关资源
最近更新 更多