从查询投影中排序字段

13

我有一个Mongo查询,可以从大型文档中提取特定的字段,类似于...

db.profiles.find(
  { "profile.ModelID" : 'LZ241M4' },
  {
    _id : 0,
    "profile.ModelID" : 1,
    "profile.AVersion" : 2,
    "profile.SVersion" : 3
  }
);

...这会产生以下输出。请注意,尽管我的投影要求在SVersion之前请求AVersion,但SVersion仍然出现在文档中的AVersion之前。

{ "profile" : { "ModelID" : "LZ241M4", "SVersion" : "3.5", "AVersion" : "4.0.3" } }
{ "profile" : { "ModelID" : "LZ241M4", "SVersion" : "4.0", "AVersion" : "4.0.3" } }

问题是我希望输出结果为...

{ "profile" : { "ModelID" : "LZ241M4", "AVersion" : "4.0.3", "SVersion" : "3.5" } }
{ "profile" : { "ModelID" : "LZ241M4", "AVersion" : "4.0.3", "SVersion" : "4.0" } }

我该如何使Mongo JavaScript shell按照我指定的字段顺序呈现查询结果?


你的查询在哪里?你考虑过使用排序吗? - jamjam
我的查询在上面。一行代码是:db.profiles.find({"profile.ModelID": 'LZ241M4'}, {_id: 0, "profile.ModelID": 1, "profile.AVersion": 2, "profile.SVersion": 3}); 我还没有考虑sort(),但那会对“行”进行排序,我正在尝试对“列”进行排序。 - Bob Kuhar
抱歉,我不知道我怎么会错过那个。我想你已经知道了,在mongodb中有“列”的概念。这是你的整个文档还是profile是更大文档的子集? - jamjam
"Profile"是一个大型文档的子文档。我在“rows”和“columns”周围加上引号,因为我知道Mongo关注的是文档和字段,但是在这次对话中,“fields”和“columns”在概念上是相似的。我的投影请求按顺序获取了“fields”,其中包括{ _id : 0, "profile.ModelID" : 1, "profile.AVersion" : 2, "profile.SVersion" : 3 },但是Mongo JavaScript shell没有以每个文档的方式生成输出。我正在寻找一种重新排列此输出的方法。感谢您的帮助。 - Bob Kuhar
4个回答

10

我通过使用别名投影字段来实现,而不是通过0和1的包含和排除来实现。 试试这个:

{
_id : 0,      
"profile.ModelID" :"$profile.ModelID", 
"profile.AVersion":"$profile.AVersion",
"profile.SVersion":"$profile.SVersion"
}

这应该是有效的选定答案。谢谢@Gulnur! - Gabriel R.

7
我现在明白了。您想按“字段”而不是字段的值返回结果排序。
简短的答案是您无法这样做。也许使用新的聚合框架可以实现这个目标。但仅为了排序字段,这似乎有些过度。
在find查询中的第二个对象用于包含或排除返回的字段,而不是用于对它们排序。
  {
    _id : 0,               // 0 means exclude this field from results
    "profile.ModelID" : 1, // 1 means include this field in the results
    "profile.AVersion" :2, // 2 means nothing
    "profile.SVersion" :3, // 3 means nothing
  }

最后一点,您不应该需要这样做,无论字段的顺序如何,都应该能够利用所需的字段。您的应用程序应该能够在不考虑字段顺序的情况下使用它所需的字段。

3
我不同意你的观点,认为按照投影建议的顺序返回字段是“过度设计”,但这是Mongo数据库;我已经习惯了失望。感谢你的帮助。 - Bob Kuhar
1
因此,“有序”和“无序”版本都代表相同的数据。在SQL中,列顺序可能对像DataReader这样的事情很重要,其中您可以按编号挑选列。但是,在MongoDB中,您实际上正在获取哈希表。没有排序功能,因为哈希表的键顺序不应该是相关的。但是,我喜欢包含数字可以是顺序的建议。这绝对值得一个JIRA票证。(http://jira.mongodb.org/) - Gates VP
1
我没有测试过这个,但根据 @Bob 得到的输出来看,“2”和“3”确实有意义:它们相当于使用“1”。也就是说,零表示不包括,非零表示包括。 - drevicko
7
从实际角度和个人偏好而言,在开发或调试过程中使用mongodb shell时,有能力对输出字段进行排序会很有帮助。我并不总是希望在执行find()时将_id字段作为第一个输出列。是的,我可能想看到_id,但我更关心其他字段,因此当它被包含在内时,总是首先看到_id可以被视为噪音。 - Inactivist
2
@GatesVP:字段顺序相关的一个显而易见的用例是在mongo shell中显示find()的结果。我已经为此提交了一张工单 - https://jira.mongodb.org/browse/SERVER-12599 - Dan Dascalescu
@DanDascalescu 我明白你的想法,但那只是一个显示问题,而且仅限于shell。试图从shell中获得漂亮的显示效果确实不是一个容易的概念,特别是对于嵌套文档和其他事物。 - Gates VP

1
我采用的另一种解决方案如下:
db.profiles
  .find({ "profile.ModelID" : 'LZ241M4' })
  .toArray()
  .map(doc => ({
    profile: {
      ModelID: doc.profile.ModelID,
      AVersion: doc.profile.AVersion,
      SVersion: doc.profile.SVersion
    }
  }))

0

自从2014年发布的2.6版本以来,MongoDB保留了文档字段在写操作后的顺序(source)。

P.S. 如果您正在使用Python,您可能会发现this很有趣。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接