7

MongoLINQプロバイダーが失敗するJSONドキュメントは次のとおりです。

{"results":
     {"text":"@twitterapi  http://tinyurl.com/ctrefg",
     "to_user_id":396524,
     "to_user":"TwitterAPI",
     "from_user":"jkoum",
     "metadata":
     {
      "result_type":"popular",
      "recent_retweets": 109
     },
     "id":1478555574, 
     "from_user_id":1833773,
     "iso_language_code":"nl",
     "source":"<a href=\"http://twitter.com/\">twitter<\/a>",
     "profile_image_url":"http://s3.amazonaws.com/twitter_production/profile_images/118412707/2522215727_a5f07da155_b_normal.jpg",
     "created_at":"Wed, 08 Apr 2009 19:22:10 +0000",
     "since_id":0,
     "max_id":1480307926,
     "refresh_url":"?since_id=1480307926&q=%40twitterapi",
     "results_per_page":15,
     "next_page":"?page=2&max_id=1480307926&q=%40twitterapi",
     "completed_in":0.031704,
     "page":1,
     "query":"%40twitterapi"}
}

「id」フィールドに注意してください。関連するC#エンティティ定義は次のとおりです。

class Twitter
{
    [BsonId]
    public ObjectId Id { get; set; }
    public Result results { get; set; }
}

private class Result
{
    public string text { get; set; }
    public int to_user_id { get; set; }
    public string to_user { get; set; }
    public string from_user { get; set; }
    public Metadata metadata { get; set; }
    public int id { get; set; }
    public int from_user_id { get; set; }
    public string iso_language_code { get; set; }
    public string source { get; set; }
    public string profile_image_url { get; set; }
    public string created_at { get; set; }
    public int since_id { get; set; }
    public int max_id { get; set; }
    public string refresh_url { get; set; }
    public int results_per_page { get; set; }
    public string next_page { get; set; }
    public double completed_in { get; set; }
    public int page { get; set; }
    public string query { get; set; }
}

class Metadata
{
    public string result_type { get; set; }
    public int recent_retweets { get; set; }
}

「Twitter」コレクションを作成して上記のドキュメントを保存すると、Mongo LINQプロバイダーを使用してクエリを実行すると、FileFormatException例外がスローされます。「要素'id'はクラスMongo.Context.Testsのフィールドまたはプロパティと一致しません。 NativeTests + Result "

ただし、この問題を修正するための2つの代替回避策があります。

  1. Resultの「id」フィールドの名前を「idd」に変更します。たとえば、JSONドキュメントとResultクラスの両方で「idd」に変更します。次に、LINQクエリが機能します。
  2. 「id」フィールドを保持しますが、さらにフィールド「Id」をResultクラスに追加し、属性[BsonId]でマークします。これで、Resultクラスには「Id」フィールドと「id」フィールドの両方が含まれますが、クエリは機能します。

私はMongoAPIを使用してコレクションをクエリしますが、すべてが正常に機能するため、これはMongoDBLINQプロバイダーのバグであるに違いないと思います。ネストされたJSON要素の「id」は予約済みの作品であってはなりませんね。

更新:ネイティブAPIクエリの実行結果は次のとおりです。

> db.Twitter.find().limit(1);

{ "_id" : ObjectId("50c9d3a4870f4f17e049332b"),
 "results" : { 
    "text" : "@twitterapi  http://tinyurl.com/ctrefg", 
    "to_user_id" : 396524, 
    "to_user" : "TwitterAPI", 
    "from_user" : "jkoum", 
    "metadata" : { "result_type" : "popular", "recent_retweets" : 109 }, 
    "id" : 1478555574, 
    "from_user_id" : 1833773, "
    iso_language_code" : "nl", 
    "source" : "<a href=\"http://twitter.com/\">twitter</a>", 
    "profile_image_url" : "http://s3.amazonaws.com/twitter_production/profile_images/118412707/2522215727_a5f07da155_b_normal.jpg", 
    "created_at" : "Wed, 08 Apr 2009 19:22:10 +0000", 
    "since_id" : 0, 
    "max_id" : 1480307926, 
    "refresh_url" : "?since_id=1480307926&q=%40twitterapi", "results_per_page" : 15,    "next_page" : "?page=2&max_id=1480307926&q=%40twitterapi", 
    "completed_in" : 0.031704, 
    "page" : 1, 
    "query" : "%40twitterapi" 
    } 
}
4

2 に答える 2

14

MongoDBでは、データベースに保存されているすべてのドキュメントに「_id」というフィールド(ルートレベル)が必要です。

C#ドライバーは、「Id」、「id」、または「_id」と呼ばれるクラス内のすべてのフィールドが、特別な「_id」フィールドにマップされることを想定しています。これは慣例であり、オーバーライドできます。C#ドライバーは、Resultクラスがコレクションのルートドキュメントとして使用されることを意図していないことを認識しないため、「id」フィールドを検索し、データベース内の「_id」にマップします。

これをオーバーライドできる1つの方法は、クラス内のフィールドの名前を変更することです(発見したとおり)。次に、[BsonElement]属性を使用して、C#フィールド名(「idd」など)をデータベースで実際に使用されている名前(「id」など)にマップすることもできます。例えば:

public class Result
{
    [BsonElement("id")]
    public int idd; // matches "id" in the database
    // other fields
}

もう1つの方法は、クラスの「Id」メンバーを見つける規則をオーバーライドして、ResultクラスのC#ドライバーのデフォルトの動作を抑制することです。これを行うには、Resultクラスに新しいConventionProfileを登録します。例えば:

var noIdConventions= new ConventionProfile();
noIdConventions.SetIdMemberConvention(new NamedIdMemberConvention()); // no names
BsonClassMap.RegisterConventions(noIdConventions, t => t == typeof(Result));

Resultクラスがマップされる前に、プログラムの非常に早い段階でこれを行う必要があります。

于 2012-12-13T22:50:43.470 に答える
0

問題は、POCOがJSONと一致しないことです

クラスにはIDとresultsTwitterというクラスがあり
ますが、JSONには結果があります。そこに問題があります。

したがって、実際には、クラスをバイパスして、次Twitterのインスタンスを作成するだけです。Result

JSONは次のようになります。

{
  _id: ObjectId("50c9c8f3e0ae76405f7d2b5e"), 
  "results": { 
     "text":"@twitterapi  http://tinyurl.com/ctrefg",
     "to_user_id":396524,
     "to_user":"TwitterAPI",
     "from_user":"jkoum",
     "metadata":
     {
      "result_type":"popular",
      "recent_retweets": 109
     },
     "id":1478555574, 
     "from_user_id":1833773,
     "iso_language_code":"nl",
     "source":"<a href=\"http://twitter.com/\">twitter<\/a>",
     "profile_image_url":"http://s3.amazonaws.com/twitter_production/profile_images/118412707/2522215727_a5f07da155_b_normal.jpg",
     "created_at":"Wed, 08 Apr 2009 19:22:10 +0000",
     "since_id":0,
     "max_id":1480307926,
     "refresh_url":"?since_id=1480307926&q=%40twitterapi",
     "results_per_page":15,
     "next_page":"?page=2&max_id=1480307926&q=%40twitterapi",
     "completed_in":0.031704,
     "page":1,
     "query":"%40twitterapi"}
    }
}

編集

あなたresultsは実際には埋め込まれたドキュメントです(現在のPOCOモデルの場合)ので、Result.IDにも[BsonId]のマークを付ける必要があります

于 2012-12-13T12:28:12.177 に答える