我有一个包含两个不同(但相似)结构的文档的集合,一些包含字段“someField”和一个字符串值,另一些包含字段“someField”和一堆子字段。
我可以查询以下两种类型的文档,当它是字符串时将someField作为字符串,如果它有子字段,可以作为某些子字段吗? (很容易得到字符串或所有子字段)
如果您可以将子字段格式化为单个字符串文档,则获得奖励。
包含两种类型文档的集合(简化示例)
{
"_id" : ObjectId("53345585cdf2fb6a03f4a7bc"),
"document" : {
"someField" : "Foo 1, Bar 2",
}
}
{
"_id" : ObjectId("533455sdfghjfb6a03f4a7bc"),
"document" : {
"someField" : {
"foo": "1",
"bar": "2",
"wibble": "I don't want this field"
}
}
}
额外信息:
我到目前为止最好的方法是使用两个查询,然后在另一个脚本或代码中将结果连接在一起:
db.someCollection.find(
{
"document.someField.foo":{$exists:false},
},
{
"document.someField": 1,
_id: 0
}
).forEach(printjson)
db.someCollection.find(
{
"document.someField.foo":{$exists:true},
},
{
"document.someField.foo": 1,
"document.someField.bar": 1,
_id: 0
}
).forEach(printjson)
答案 0 :(得分:1)
您的问题有点抽象,但您可以使用.aggregate()
和$project
运算符来处理此类解决方案:
db.collection.aggregate([
{ "$project": {
"onefield": { "$cond": [
"$document.someField.foo",
{
"foo": "$document.someField.foo",
"bar": "$document.someField.bar"
},
"$document.someField"
]}
}}
])
这也使用了三元$cond
运算符,以便评估"结果如何。
因此,如果您的商品执行包含子文档字段,那么您可以重新塑造"到你想要的领域。当他们不时,您可以按照或(如果您的逻辑需要)展示字段,再嵌套$cond
操作以确定如何处理该领域。
当然,如果您真的希望所有内容都是字符串,那么请使用$concat
代替:
db.collection.aggregate([
{ "$project": {
"onefield": { "$cond": [
"$document.someField.foo",
{ "$concat": [
"Foo ",
"$document.someField.foo",
" ,Bar ",
"$document.someField.bar"
]},
"$document.someField"
]}
}}
])
答案 1 :(得分:0)
我认为@Neil-Lunn's answer可能更好(我仍在努力将其转换为我的真实世界示例),但我设法使用JS函数自己完成。 *简化了我的真实世界,因此可能包含拼写错误。
db.someCollection.find()
.forEach(function(o) {
if(o.document.someField.foo) {
print("Foo "
+ o.document.someField.foo
+ ", Bar "
+ o.document.someField.bar
);
} else {
print(o.document.someField);
}
}
)
条件检查foo是否存在(undefined为false),然后在必要时进行一些手动字符串连接。