将 SQL 表转换为 mongoDB 文档

Posted

技术标签:

【中文标题】将 SQL 表转换为 mongoDB 文档【英文标题】:Convert SQL table to mongoDB document 【发布时间】:2010-12-07 01:30:18 【问题描述】:

将 SQL 数据库(比如 1 个表)转换为 mongoDB 文档的最佳方法是什么?

我想我可以使用 C# 驱动程序并实现一个循环,它选择表中的每一行并将其保存在 Mongo 中。但是,我正在寻找一种更好的方法来转换大量数据。

【问题讨论】:

MongoDB 的理念是将尽可能多的这类事情推到驱动程序/应用程序级别......所以我同意下面的 Matt ......你最好的选择是使用 C# 不仅因为它会为您节省 很多 的麻烦(使用它的好 BSON 库)而且还因为您可以处理许多数据转换问题,而不是说转储或导出等。 【参考方案1】:

这是我用于将数据从 SQL 服务器导入到位于我的盒子上的 Mongodb 的导入脚本。 这段代码只会在 MongoDB 中创建一个类似的表(存在于 SQL DB 中)。 您可以提供要以逗号分隔的表格列表导入,所有这些都可以毫无问题地导入。

static void Main(string[] args)

    List<string> tablelist = new List<string>();
    if (!args[0].Contains(','))
        tablelist.Add(args[0]);
    else
        tablelist.AddRange(args[0].Split(','));
    string sqlconnectionstring = ConfigurationManager.ConnectionStrings["ConnectionString"].ToString();
    var connectionString = "mongodb://localhost/?safe=true;w=1;wtimeout=30s";
    var safemode = SafeMode.True;
    MongoServer server = MongoServer.Create(connectionString);
    MongoDatabase db = server.GetDatabase("testdb");
    MongoCollection<MongoDB.Bson.BsonDocument> coll = db.GetCollection<BsonDocument>("test");
    //coll.Find().Count();
    int i = 0;
    foreach (string table in tablelist)
    

        using (SqlConnection conn = new SqlConnection(sqlconnectionstring))
        
            string query = "select * from " + table;
            using (SqlCommand cmd = new SqlCommand(query, conn))
            
                /// Delete the MongoDb Collection first to proceed with data insertion

                if (db.CollectionExists(table))
                
                    MongoCollection<BsonDocument> collection = db.GetCollection<BsonDocument>(table);
                    collection.Drop();
                
                conn.Open();
                SqlDataReader reader = cmd.ExecuteReader();
                List<BsonDocument> bsonlist = new List<BsonDocument>(1000);
                while (reader.Read())
                
                    if (i == 1000)
                    
                        using (server.RequestStart(db))
                        
                            //MongoCollection<MongoDB.Bson.BsonDocument> 
                            coll = db.GetCollection<BsonDocument>(table);
                            coll.InsertBatch(bsonlist);
                            bsonlist.RemoveRange(0, bsonlist.Count);
                        
                        i = 0;
                    
                    ++i;
                    BsonDocument bson = new BsonDocument();
                    for (int j = 0; j < reader.FieldCount; j++)
                    
                        if (reader[j].GetType() == typeof(String))
                            bson.Add(new BsonElement(reader.GetName(j), reader[j].ToString()));
                        else if ((reader[j].GetType() == typeof(Int32)))
                        
                            bson.Add(new BsonElement(reader.GetName(j), BsonValue.Create(reader.GetInt32(j))));
                        
                        else if (reader[j].GetType() == typeof(Int16))
                        
                            bson.Add(new BsonElement(reader.GetName(j), BsonValue.Create(reader.GetInt16(j))));
                        
                        else if (reader[j].GetType() == typeof(Int64))
                        
                            bson.Add(new BsonElement(reader.GetName(j), BsonValue.Create(reader.GetInt64(j))));
                        
                        else if (reader[j].GetType() == typeof(float))
                        
                            bson.Add(new BsonElement(reader.GetName(j), BsonValue.Create(reader.GetFloat(j))));
                        
                        else if (reader[j].GetType() == typeof(Double))
                        
                            bson.Add(new BsonElement(reader.GetName(j), BsonValue.Create(reader.GetDouble(j))));
                        
                        else if (reader[j].GetType() == typeof(DateTime))
                        
                            bson.Add(new BsonElement(reader.GetName(j), BsonValue.Create(reader.GetDateTime(j))));
                        
                        else if (reader[j].GetType() == typeof(Guid))
                            bson.Add(new BsonElement(reader.GetName(j), BsonValue.Create(reader.GetGuid(j))));
                        else if (reader[j].GetType() == typeof(Boolean))
                        
                            bson.Add(new BsonElement(reader.GetName(j), BsonValue.Create(reader.GetBoolean(j))));
                        
                        else if (reader[j].GetType() == typeof(DBNull))
                        
                            bson.Add(new BsonElement(reader.GetName(j), BsonNull.Value));
                        
                        else if (reader[j].GetType() == typeof(Byte))
                        
                            bson.Add(new BsonElement(reader.GetName(j), BsonValue.Create(reader.GetByte(j))));
                        
                        else if (reader[j].GetType() == typeof(Byte[]))
                        
                            bson.Add(new BsonElement(reader.GetName(j), BsonValue.Create(reader[j] as Byte[])));
                        
                        else
                            throw new Exception();
                    
                    bsonlist.Add(bson);
                
                if (i > 0)
                
                    using (server.RequestStart(db))
                    
                        //MongoCollection<MongoDB.Bson.BsonDocument> 
                        coll = db.GetCollection<BsonDocument>(table);
                        coll.InsertBatch(bsonlist);
                        bsonlist.RemoveRange(0, bsonlist.Count);
                    
                    i = 0;
                
            
        
    

【讨论】:

使用 MongoServer、MongoDatabase 等类型需要添加哪些参考?我有 MongoDB.BSON、MongoDB.Driver 和 MongoDB.Driver.Core,但这些行代码在 VIsual Studio 中是红色的。 我也希望运行此代码,但无法使用当前的 MongoDB 驱动程序包进行编译。没有找到 MongoServer、MongoDatabase 类?谢谢,洛杉矶人【参考方案2】:

驱动方式是 FAR 最直接的方式。导入/导出工具非常棒,但当您将它们成对使用时。如果您的表包含日期并且您尝试从 db 导出并导入到 mongo,那么您将大吃一惊。

你也很幸运,在 c# 中。我们正在使用 ruby​​,并且有一个 3200 万行的表,我们迁移到了 mongo。我们的最终解决方案是在 postgres 中制作一个疯狂的 sql 语句,该语句输出 json(包括一些使日期正常运行的非常笨拙的东西)并将命令行上该查询的输出通过管道传输到 mongoimport。写了令人难以置信的令人沮丧的一天,而且不是那种可以真正改变的东西。

因此,如果您可以摆脱它,请使用带有 mongo 驱动程序的 ado.net。如果没有,我祝你好运:-)

(请注意,这是来自一个完全的 mongo fanboi)

【讨论】:

除了日期格式,还有其他Mongo在转换过程中不喜欢的类型吗? 日期对我们来说是真正的杀手,因为 mongo 将它视为自纪元以来的 64 位滴答数,而我们使用的其他所有内容都使用 32 位日期。我们在 tsv 模式下导入时遇到问题,因为显然根据 10gen,带引号的字符串在 tsv 文件中不能有换行符。我们也遇到了其他问题,但它们更具体到我们的工具。【参考方案3】:

我必须为此创建工具。 它使用 bcp.exe 将数据导出为 xml,然后使用 Newtonsoft JSON.NET 将其转换为 json,然后使用 mongoimport 将其导入。用了不到一天的时间,但不支持日期。

下面的一些代码(非常未清理:)

bcp.exe 使用如下语法: bcp.exe "SELECT * from GeoData.dbo.Airports FOR XML RAW('Row'),ROOT('Root'),ELEMENTS" queryout D:\TEMP\tmp1045.tmp -Uxxxx -Pxxxx -Sxxxx -w -r " " -q

json:

var r=XmlReader.Create("file://D:/1.xml");
    XmlDocument xdoc=new XmlDocument();
    xdoc.Load(r);
    string result="";





    //o["Root"]["Airport"];
    foreach(XmlNode n in xdoc.ChildNodes[0])
        var rr= JsonConvert.SerializeXmlNode(n);    

        JObject o=JObject.Parse(rr);    

        var co=o.Children().Children().First();     

        foreach (JToken c in co.Children().Where(cc=>cc.Type==JTokenType.Property).ToList())                   
            var prop=c as JProperty;            
            double d;
            if (double.TryParse(co[prop.Name].Value<string>(),out d))
            
                co[prop.Name] = d;
                       
            //c.Value<string>().Dump();
            //c.Value<string>().Dump();
            //co[c.Name]
        

        //co["APT_Latitude"].Value<decimal>().Dump();       
        result=result + co.ToString(Newtonsoft.Json.Formatting.None)+"\r\n";


    
    File.WriteAllText("D:/1.json",result);

    //result.Dump();

蒙古进口: D:\MongoDB\mongoimport.exe -c "test" -d "MongoStatic" 1.json >1

【讨论】:

【参考方案4】:

如果你喜欢玩 Ruby,我制作了一个可以帮助你做到这一点的 gem:http://mongify.com/。

源码可以找到:https://github.com/anlek/mongify/

非常简单直接地定义您的架构以及它应该如何转换为 mongodb。包括嵌入、重命名表、重命名字段和一堆其他选项。

【讨论】:

【参考方案5】:

Norm 和 samus c# mongo 驱动程序都支持作为文档传递的强类型类。意味着它像 Nhiberbate 和 LINQ to SQL 一样酷。

所以我的想法是,您可以使用 LINQ to SQL 在 c# 中创建一个实体(表示表的类)以从 sql server 检索数据,并且您可以使用相同的强类型类插入 mongo db。

确保您的类在任一字段中都应具有 mongo 标识符 属性(在 NoRM 中)。这是为文档生成唯一的 id。

【讨论】:

以上是关于将 SQL 表转换为 mongoDB 文档的主要内容,如果未能解决你的问题,请参考以下文章

使用SQL将字符串列转换为mongodb中的日期时间

使用 SQL 将字符串列转换为 mongodb 中的日期时间

将Mongodb的表导入到Hive中

将 XML 转换为 SQL Server 表(cfdi 文档)

MongoDB学习总结 —— Windows平台下安装

MongoDB :: 将 SQL 转换为 MongoDB