Design patterns MongoDB中的动态标签策略

Design patterns MongoDB中的动态标签策略,design-patterns,mongodb,tags,Design Patterns,Mongodb,Tags,在Facebook上,你可以开始键入@并标记用户的状态。这个问题不是关于前端,而是关于如何存储该功能的数据。以动态方式在字符串中表示任何mongodb实体的通用方式实现此功能的最佳方式是什么。目标是,如果实体更改,则存储字符串中的表示形式也会更改。例如,我的一个想法是: Post: { _id: "48ajsdlfhsdjfkjsljsd" name: "Post One", text: "@user is the best for liking @thing, and

在Facebook上,你可以开始键入@并标记用户的状态。这个问题不是关于前端,而是关于如何存储该功能的数据。以动态方式在字符串中表示任何mongodb实体的通用方式实现此功能的最佳方式是什么。目标是,如果实体更改,则存储字符串中的表示形式也会更改。例如,我的一个想法是:

Post: {
    _id: "48ajsdlfhsdjfkjsljsd"
    name: "Post One",
    text: "@user is the best for liking @thing, and @thing"
    tags: [user:1234, thing:456, thing:789]
}

所以我会加载这篇文章,然后查看标签,加载每个标签类型和id的模型,然后重写字符串:“Chris最喜欢StackOverflow和Mongo”。这似乎效率低下,有更好的想法吗?

虽然不太确定您想做什么,但我建议如下:

  • 创建一个文档,作为字符串中“@”标记与MongoDB文档中字段之间的映射

  • 修改Post文档,使标记数组包含标准化文档,这些文档既可以标识存储真实数据的文档的_id值,也可以标识在这些文档中获取数据的字段

  • (可选)修改您的Post文档,以显式包含映射文档_id。如果存在全局映射文档,则这将是不必要的,但

  • 在您的示例中,映射文档可能如下所示:

    Mapping: { _id: "abc..", maps: [{tag:"user", field:"user.person.nickname"}, {tag:"thing", field:"object.name"}] }
    
    Post: { _id: "48ajsdlfhsdjfkjsljsd",
      name: "Post One",
      text: "@user is the best for liking @thing, and @thing",
      tags: [{tag:"user", docId:"pqr..."}, {tag:"thing", docId:"xzy..."}, {tag:"thing", docId:"mno..."}],
      mapping: "abc..."
    }
    
    post文档的外观如下所示:

    Mapping: { _id: "abc..", maps: [{tag:"user", field:"user.person.nickname"}, {tag:"thing", field:"object.name"}] }
    
    Post: { _id: "48ajsdlfhsdjfkjsljsd",
      name: "Post One",
      text: "@user is the best for liking @thing, and @thing",
      tags: [{tag:"user", docId:"pqr..."}, {tag:"thing", docId:"xzy..."}, {tag:"thing", docId:"mno..."}],
      mapping: "abc..."
    }
    
    然后需要执行以下操作以返回文本字符串:

  • 加载Post文档
  • 提取并加载映射文档(如果此映射是全局映射,则不需要此步骤)
  • 在一次加载中加载与基础数据对应的所有文档:

    find({u id:{$in:[“pqr…”,“xyz…”,“mno…”})

  • 从每个定位的文档中检索“所需文档”字段中的值

  • 用字段值替换标记
  • 这种方法允许您更改字符串中标记的含义(通过更改映射文档-例如,您可以将@user从昵称更改为realname)和标记的值(通过更改Post文档中标记列表中存储的docid),但字符串生成至少还有4个步骤


    这种方法无法处理映射文档不包含标记的情况,或者标记列表的大小与文本字符串中的标记数不相同的情况。

    虽然不太确定要执行的操作,但我建议如下:

  • 创建一个文档,作为字符串中“@”标记与MongoDB文档中字段之间的映射

  • 修改Post文档,使标记数组包含标准化文档,这些文档既可以标识存储真实数据的文档的_id值,也可以标识在这些文档中获取数据的字段

  • (可选)修改您的Post文档,以显式包含映射文档_id。如果存在全局映射文档,则这将是不必要的,但

  • 在您的示例中,映射文档可能如下所示:

    Mapping: { _id: "abc..", maps: [{tag:"user", field:"user.person.nickname"}, {tag:"thing", field:"object.name"}] }
    
    Post: { _id: "48ajsdlfhsdjfkjsljsd",
      name: "Post One",
      text: "@user is the best for liking @thing, and @thing",
      tags: [{tag:"user", docId:"pqr..."}, {tag:"thing", docId:"xzy..."}, {tag:"thing", docId:"mno..."}],
      mapping: "abc..."
    }
    
    post文档的外观如下所示:

    Mapping: { _id: "abc..", maps: [{tag:"user", field:"user.person.nickname"}, {tag:"thing", field:"object.name"}] }
    
    Post: { _id: "48ajsdlfhsdjfkjsljsd",
      name: "Post One",
      text: "@user is the best for liking @thing, and @thing",
      tags: [{tag:"user", docId:"pqr..."}, {tag:"thing", docId:"xzy..."}, {tag:"thing", docId:"mno..."}],
      mapping: "abc..."
    }
    
    然后需要执行以下操作以返回文本字符串:

  • 加载Post文档
  • 提取并加载映射文档(如果此映射是全局映射,则不需要此步骤)
  • 在一次加载中加载与基础数据对应的所有文档:

    find({u id:{$in:[“pqr…”,“xyz…”,“mno…”})

  • 从每个定位的文档中检索“所需文档”字段中的值

  • 用字段值替换标记
  • 这种方法允许您更改字符串中标记的含义(通过更改映射文档-例如,您可以将@user从昵称更改为realname)和标记的值(通过更改Post文档中标记列表中存储的docid),但字符串生成至少还有4个步骤


    这种方法无法处理映射文档不包含标记的情况,或者标记列表的大小与文本字符串中标记的数量不相同的情况。

    您的答案很有效,但我正在寻找更有效的方法。我所做的就是像这样在Mongo中存储一个文档

    {
        _id: "4bdslakjghjdgkjsh123",
        title: "Post One",
        text: "@ is cool for liking @",
        tags: ["user:4bcasdkasd89", "product:4basfkjafkjlfl"]
    }
    
    用于翻译标记的代码在加载消息后运行。它基本上使用标签来知道要使用哪种类型的模型,以及加载它的id。然后使用模型的as_标记方法或to_s创建一个值数组。然后将该数组替换为原始字符串,以替换@符号。很像斯普林特。所以它被翻译成“克里斯喜欢自行车很酷”


    有什么办法可以提高这里的效率吗?

    你的答案很有效,杰夫,但我一直在寻找更有效的方法。我所做的就是像这样在Mongo中存储一个文档

    {
        _id: "4bdslakjghjdgkjsh123",
        title: "Post One",
        text: "@ is cool for liking @",
        tags: ["user:4bcasdkasd89", "product:4basfkjafkjlfl"]
    }
    
    用于翻译标记的代码在加载消息后运行。它基本上使用标签来知道要使用哪种类型的模型,以及加载它的id。然后使用模型的as_标记方法或to_s创建一个值数组。然后将该数组替换为原始字符串,以替换@符号。很像斯普林特。所以它被翻译成“克里斯喜欢自行车很酷”

    有什么办法提高这里的效率吗