我遇到了多个具有相同名称的字段的问题。
让我们考虑以下代码:
mongo_client = MongoClient.new("localhost", 27017)
db = mongo_client.db("mydb")
coll = db.collection("test")
coll.remove
#create an entry
customer = {:id => 321, :name => "test customer"}
coll.save customer
#find the entry and modify it
customer = coll.find(:id => 321).to_a.first
customer[:name] = "test customer 2"
coll.save customer
#find again and print
customer = coll.find(:id => 321).to_a.first
pp customer
输出符合预期:
{"_id"=>BSON::ObjectId('52e254c5990300785b000001'),
"name"=>"test customer 2",
"id"=>321}
但 robomongo 显示现在有两个名称字段:
这很奇怪。
所以我的两个问题是:
答案 0 :(得分:3)
我无法直接回答您的问题,但可以解释为什么您只在Ruby程序中看到一个带有“name”的字段,而Robomongo则显示两个字段:
请查看此页面上的“字段名称”部分:http://docs.mongodb.org/manual/core/document/
它说:
BSON文档可能有多个具有相同名称的字段。最 但是,MongoDB接口代表具有结构的MongoDB(例如, 哈希表),不支持重复的字段名称。如果你需要 操纵具有多个具有相同字段的文档 名称,请参阅驱动程序的驱动程序文档。
内部MongoDB进程创建的一些文档可能有 重复字段,但没有MongoDB进程会添加重复 字段到现有用户文档。
所以看起来你的MongoDB for Ruby会将文档映射到不支持重复字段名称的哈希结构。
也许暂时切换到Robomongo使用的驱动程序可以帮助解决您的问题。之后,您可以返回使用MongoDB。
根据您的MongoDB版本,我认为您可以通过将--objcheck
传递到mongod
进程来阻止文档中的重复字段名称。
摘自手册:
- objcheck强制mongod在收到客户端时验证所有请求,以确保客户端永远不会插入无效文档 进入数据库。对于具有高度子文档的对象 嵌套, - objcheck可以对性能产生很小的影响。您可以 set --noobjcheck在运行时禁用对象检查。改变了 版本2.4:MongoDB默认启用--objcheck,以防止任何 客户端将错误或无效的BSON插入MongoDB 数据库中。
我希望这有帮助!
答案 1 :(得分:1)
以下C ++代码将连接到您的本地MongoDB服务器,并将BSON文档插入 tutorial.persons 集合中。创建的文档具有重复的键(“名称”使用两次)。当我们查询所有人的集合并显示每个文档的字段时,您将看到“名称”字段出现两次。
这证明C ++ MongoDB驱动程序可能更适合于多次使用相同字段名称的插入和查询文档。
#include "mongo/client/dbclient.h"
#include <iostream>
void show_all_persons(mongo::DBClientConnection & c) {
// Iterate over the collection in which we've just inserted the person object
std::auto_ptr<mongo::DBClientCursor> cursor = c.query("tutorial.persons", mongo::BSONObj());
while (cursor->more()) {
mongo::BSONObj d = cursor->next();
std::cout << "The document "
<< d.toString()
<< " contains " << d.nFields() << " field(s)."
<< std::endl;
}
}
int main() {
try {
// Connect
mongo::DBClientConnection c;
c.connect("localhost");
// Prepare BSON "person" document to insert (notice duplicate key "name")
mongo::BSONObj p = BSON( "name" << "Alice" << "name" << "Bob" );
c.insert("tutorial.persons", p);
show_all_persons(c);
} catch( const mongo::DBException &e ) {
std::cout << "caught " << e.what() << std::endl;
}
return EXIT_SUCCESS;
}
以上是运行上述代码时的输出:
The document { _id: ObjectId('52e282cd84a7df0a1975eb8b'), name: "Alice", name: "Bob" } contains 3 field(s).
您可以使用这个hacky CMakeLists.txt文件进行编译:
project(bsoncpp)
cmake_minimum_required(VERSION 2.8)
aux_source_directory(. SRC_LIST)
include_directories(${Boost_INCLUDE_DIRS})
link_directories(${Boost_LIBRARY_DIRS})
add_executable(bsoncpp ${SRC_LIST})
target_link_libraries(bsoncpp /usr/lib/libmongoclient.a -lboost_system -lboost_thread -lboost_filesystem -lpthread -lssl -lcrypto)
我希望这会有所帮助。现在由您来删除不需要的重复字段。
玩得开心!
答案 2 :(得分:1)
我使用代码来回答我的问题 2)我怎样才能首先防止这种情况?是:使用方法 Mongo :: Collection的组合: :更新和操作 $ set 。
示例代码:
mongo_client = MongoClient.new("localhost", 27017)
db = mongo_client.db("mydb")
coll = db.collection("test")
coll.remove
#create an entry
customer = {:id => 321, :name => "test customer"}
coll.save customer
#Now comes the important part! find the entry and modify it
coll.update({:id => 321}, {"$set" => {:name => "test customer 2"}}, {})