这两天在工作中被Mongo集合存储给整得头大,当然也是我的认知太浅,所以下面我来分享下我所遇到的这个问题希望有大佬能给出更好的解决方案,
1.需求:
存储一个从前端接收未知数据类型的集合
例:
由于是未知的数据类型,所有我创建了一个IList<Object>集合
public class Demo { public String Name { get; set; } public List<Object> List { get; set; } }
2.问题
按照我们平常的想法我们只要将数据从api接收到并且进行存储即可,那么事实真是如此吗,下面我们来进行一个简单的测试
首先创建api
[RoutePrefix("Home")] public class HomeController : ApiController { public HomeController() { } //连接地址 private static string conn = "mongodb://192.168.11.51:40000"; //数据库名称 private static string dbName = "yan"; //集合名称 private static string colName = "Demo"; static MongoClient client = new MongoClient(conn); //获取指定数据库 static IMongoDatabase db = client.GetDatabase(dbName); //获取指定集合 BsonDocument数据库文档对象 static IMongoCollection<Demo> coll = db.GetCollection<Demo>(colName); [HttpPost] [Route("TestMongo")] public void TestMongo([FromBody] Demo demo) { coll.InsertOne(demo); } }
从上面可以看出我们在TestMongo只做了一件事,就是讲接收到的数据进行存储,
然后我们使用PostMan进行模拟请求测试
可以看到后台如愿的获取到了请求数据,那么存储到Mongo中是什么呢,我们来看一下
可以看到这个集合存储到Mongo中变成了一组我们几乎看不懂的数据结构,那么这到底是怎么回事,下面我解析下我猜想的跟其解决方法。
3.解决方案
首先我们来获取解析下从客户端接收到的集合类型
我们可以看到集合中存储的每一个类型是JObject类型,而展开这个类型时发现里面数据结构好像根本无法解析所以导致我们在存储时并没有按照我们所想的那样进行存储,那么该怎么进行解决呢,整了两天整出了一个不算好的解决方案,
首先将集合改成IEnumberable<Object>类型(后面解释其原因)
public class Demo { public String Name { get; set; } public IEnumerable<Object> List { get; set; } }
然后在api中做一些特殊处理
public void TestMongo([FromBody] Demo demo) { //1.将集合包装成一个Object集合序列化 String strVal = JsonConvert.SerializeObject(new { data = demo.List }); //2.将序列化的字符串转换成BsonDocument类型 BsonDocument doc = BsonDocument.Parse(strVal); //3.使用BsonDocument获取被包装的集合并转换成BsonArray类型 var docArr = doc.GetValue("data").AsBsonArray; //4.获取BsonArray的Values值并重写赋给原集合引用 //【因为Values值是IEnumerable<BsonValue>类型,所以原集合必须是IEnumerable<Object>类型】 demo.List = doc.Values; coll.InsertOne(demo); }
上面代码我们就可以将集合按照我们所想那样进行存储,我们来看一下效果
上面方案我感觉并不好,但是并没有找到更好的方法,在此希望各位大佬能给出更好的解决方案