【问题标题】:Querying MongoDB embedded documents, not arrays, in a tabular format以表格格式查询 MongoDB 嵌入文档,而不是数组
【发布时间】:2017-11-14 16:38:13
【问题描述】:

我将以下 JSON 导入 MongoDB(mongoimport --host localhost --db test --collection employees --type json --file Employees.json --jsonArray)

[ 
    {
        "Employee" : {
            "Basics" : {
                "Name" : "James Bond",
                "Age" : 42
            },
            "Addresses" : {
                "Address" : {
                    "City" : "London",
                    "Country" : "England"
                },
                "Address" : {
                    "City" : "Paris",
                    "Country" : "France"
                }
            },
            "Cars" : {
                "Car" : {
                    "Model" : "Aston Martin",
                    "Year" : 1977
                },
                "Car" : {
                    "Model" : "Audi",
                    "Year" : 2000
                }
            }
        }
    },
    {
        "Employee" : {
            "Basics" : {
                ..
            },
            "Addresses" : {
                "Address" : {
                    ..
                },
                "Address" : {
                    ..
                }
            },
            "Cars" : {
                "Car" : {
                    ..
                }
            }
        }
    }
]

为了以表格格式获取结果,我使用了以下查询,但它只获取阿斯顿马丁而不是奥迪。

db.employees.aggregate( 
[
{$match: {'Employee.Basics.Name':{$eq:"James Bond"}}},
{$project: {carModel:'$Employee.Cars.Car.Model',_id:0}}
]); 
  1. 有没有一种方法可以获得两个值? (以表格格式与 特定领域 - 不喜欢 db.getCollection('employees').find({'Employee.Basics.Name':{$eq:"James 债券"}});)
  2. 查看其他示例,看起来 JSON 应该有汽车和地址数组,有没有办法可以更新 MongoDB 中的文档以现在将它们更改为数组?

我是 MongoDB 的新手,(才 2 天大 :))所以任何指针都会有很大帮助。 提前致谢!

【问题讨论】:

  • “表格格式”是什么意思?您能否在问题中包含您需要的示例输出?
  • > db.getCollection('employees').find({'Employee.Basics.Name':{$eq:"James Bond"}}, { _id: 0, 'Employee.Cars.Car.Model' : 1 }); { "Employee" : { "Cars" : { "Car" : { "Model" : "Aston Martin" } } } } > db.employees.aggregate([{$match: {'Employee.Basics.Name':{$eq:"James Bond"}}},{$project: {carModel:'$Employee.Cars.Car.Model',_id:0}}]); { "carModel" : "阿斯顿马丁" }
  • 第一个结果是分层的,第二个是表格的(对不起,我可能使用了错误的术语,但我想你可以看到区别)。 此外,这两个查询都只返回阿斯顿马丁,但詹姆斯邦德还拥有一辆奥迪
  • @joy_jedi 关于人们要求您澄清的内容,您似乎缺少的是您的 "Car" 元素实际上在其下方显示了 "Car" 的 2 个键。这对于支持 MongoDB 的 JSON 或 BSON 存储无效。因此,您根本无法拥有该格式的文档。如果您确实尝试导入它,您会发现只有 "one" Car,因为那将是有效的 JSON,并且第二个“key”替换了第一个。简而言之,这应该是一个“数组”。所以不清楚你在问哪个。如何查询?或者如何“导入”。似乎是后者。
  • 感谢@NeilLunn 的回复。后来我意识到,由于重复的键,我在进行 XML2JSON 转换后得到的 JSON 不是有效的 JSON。奇怪的是,MongoDB 允许我导入它但不能查询它。 (不确定 MongoDB 在导入时是否应该抱怨,但事实并非如此)。另外,当我做 Mongoexport 时,我确实看到了两辆汽车。在导入之前,我将发布我编写的用于将 Cars 和 Addresses 转换为 json 中的数组的 Java 代码。

标签: json mongodb mongodb-query


【解决方案1】:

如果有人在我的示例中使用格式不正确的 JSON,您可以使用下面的 Java 代码来修复它。 (我通过使用https://sourceforge.net/projects/xml2json-converter/ 获得了 JSON)。

private final Deque<Integer> arrayStack = new ArrayDeque<Integer>();
private final Deque<Integer> arrayElemStack = new ArrayDeque<Integer>();

String[] arrayElemNames = {"Employee","Address","Car"};
String[] arrayNames = {"Addresses","Cars"};

public void cleanJSON() throws IOException {

    try (BufferedWriter writer = Files.newBufferedWriter(Paths.get(outputJsonFileName))) {
        try (Stream<String> stream = Files.lines(Paths.get(inputJsonFileName))) {
            stream.map((str) -> formatRootElem(str)).map((str) -> formatArrayElems(str))
                    .map((str) -> formatArrays(str)).forEach((str) -> writeToOutput(writer, str));
        }
    }

}

private void writeToOutput(BufferedWriter writer, String str) {
    try {
        writer.write(str + "\n");
    } catch (IOException e) {
        e.printStackTrace();
    }
}

private String formatRootElem(String str) {
    if (str.equals("{")) {
        return "[";
    } else if (str.equals("}")) {
        return "]";
    } else if ((str.contains("Employees") && str.contains("{")) || str.equals("  }")) {
        return "";
    }
    return str;
}

private String formatArrayElems(String str) {
    if (checkInArray(str, arrayElemNames)) {
        arrayElemStack.push(1);
        return "{" + str;
    }
    if (!arrayElemStack.isEmpty()) {
        if (str.contains("{")) {
            int count = arrayElemStack.pop();
            arrayElemStack.push(++count);
        } else if (str.contains("}")) {
            int count = arrayElemStack.pop();
            --count;
            if (count == 0) {
                str = str.replace("}", "}}");
            } else {
                arrayElemStack.push(count);
            }
        }
    }
    return str;
}

private String formatArrays(String str) {
    if (checkInArray(str, arrayNames)) {
        str = str.replace('{', '[');
        arrayStack.push(1);
    } else if (!arrayStack.isEmpty()) {
        if (str.contains("{")) {
            int count = arrayStack.pop();
            arrayStack.push(++count);
        } else if (str.contains("}")) {
            int count = arrayStack.pop();
            --count;
            if (count == 0) {
                str = str.replace('}', ']');
            } else {
                arrayStack.push(count);
            }
        }
    }
    System.out.println(str);
    return str;
}

private boolean checkInArray(String str, String[] strArray) {
    for (String arrayElem : strArray) {
        if (str.contains(arrayElem) && str.contains(":")) {
            return true;
        }
    }
    return false;
}

【讨论】:

    猜你喜欢
    • 2021-08-07
    • 2015-02-06
    • 1970-01-01
    • 1970-01-01
    • 2021-03-24
    • 2021-04-14
    • 1970-01-01
    • 2015-08-30
    • 2015-03-26
    相关资源
    最近更新 更多