如何从ForerunnerDb集合中选择最新版本的对象

时间:2017-01-07 14:45:13

标签: javascript forerunnerdb

我有一个包含一系列随时间生成的对象的集合。由于我在同一个集合中存储了不同的类型,因此每个对象都有TypeIdUID(其中UID标识随时间推移引用同一实体的对象)。我正在尝试从集合中选择最新的对象,并且在没有手动迭代查询结果的情况下遇到严重的困难而无法手动迭代查询结果 - 我宁愿避免,因为我认为当集合变大时它会变得昂贵

例如:

var db; // assigned elsewhere
var col = db.collection("res");
col.primaryKey("resId");
col.insert({
    resId: 1,
    TypeId: "Person",
    UID: "Bob",
    Data: {Age: 20, Name:Bob}
});
col.insert({
    resId: 2,
    TypeId: "Person",
    UID: "Bob",
    Data: {Age: 25, Name:Bob}
});
col.insert({
    resId: 3,
    TypeId: "Car",
    UID: "TeslaModelX",
    Data: {Manufacturer: "Tesla", Owner:"Bob"}
});
col.insert({
    resId: 4,
    TypeId: "Person",
    UID: "Bill",
    Data: {Age: 22, Name:Bill}
});

从col,我希望查询选择TypeId="Person"resId降序排列的所有对象,即我希望按顺序选择对象4和2。

上面的集合是设计的,但实际上我预计肯定会有000个条目和可能的0000,每个UID可能有00个版本。换句话说,我不会返回完整的对象集合,无论是分组还是其他对象,都要迭代它。

我尝试了以下操作,但由于$distinct运算符在$orderBy之前应用,因此无法提供帮助:

col.find(
    {
        TypeId : {$eq : "Person"}
        $distinct: { UID: 1}
    },
    {
        $orderBy: {
            resId : -1
        }
    }
    );

我想到我应该能够使用$groupBy$limit$aggregate子句来识别每组所需的ID,然后使用子查询来查找精确的(非聚合的)元素,但到目前为止我还没有设法做任何我想做的事情。有什么想法吗?

我当前的解决方案是在我的对象中包含Deleted属性,并在插入新条目之前将数据库中所有现有的未删除对象设置为true。这让我可以做我想做的事,但也阻止我,例如,在已知的时间范围内选择最好的可用时间或类似的。

1 个答案:

答案 0 :(得分:1)

您可以这样做:

// TagsMenu component, top level
class TagsMenu extends Component {
  render() {
    return (
      <div>
        {
          this.props.userGroup.users.edges.map(u => {
            return <UserTagGroup user={u.node} />
          })
        }
      </div>
    )
  }
}

fragment on UserGroup {
  users(first: 1000) {
    edges {
      node {
        ${UserTagGroup.getFragment('user')}
      }
    }
  }
}


// UserTagGroup, second component
class UserTagGroup extends Component {
  render() {
    return (
      <div>
        <h4>User:  {this.props.user.id}</h4>
        {
          this.props.user.Tags.edges.map(t => {
            return <TagMenuItem tag={t.node} />
          })
        }
      </div>
    )
  }
}
fragment on User {
  id
  listingTags(first: 1000) {
    edges {
      node {
        ${TagMenuItem.getFragment('tag')}
      }
    }
  }
}


// TagMenuItem, bottom level component. Renders 1 Tag.
class TagMenuItem extends Component {
  render() {
    return (
      <div>
        {this.props.tag.tagName}
      </div>
    )
  }
}
fragment on Tag {
  tagName
  id
}

它有点脏,因为它没有整齐地包裹在一个命令中,但它就像你在ForerunnerDB v1.x中得到它一样干净。

版本2将有一个新的查询管道系统,允许这种用法,如下所示:

var tmpObj = {};
col.sort({resId: -1}, coll.find({
    "TypeId": "Person"
})).filter(function (doc) {
    return col._match(doc, {
        $distinct: {
            UID: 1
        }
    }, {}, 'and', tmpObj);
});

来源:我是ForerunnerDB的开发者。