MongoDB
 sql >> डेटाबेस >  >> NoSQL >> MongoDB

सी # के साथ कुल $ लुकअप

JSON को पार्स करने की कोई आवश्यकता नहीं है। यहाँ सब कुछ वास्तव में सीधे LINQ या एग्रीगेट फ़्लुएंट इंटरफेस के साथ किया जा सकता है।

केवल कुछ प्रदर्शन कक्षाओं का उपयोग करना क्योंकि प्रश्न वास्तव में आगे बढ़ने के लिए बहुत कुछ नहीं देता है।

सेटअप

मूल रूप से हमारे यहां दो संग्रह हैं,

इकाइयाँ

{ "_id" : ObjectId("5b08ceb40a8a7614c70a5710"), "name" : "A" }
{ "_id" : ObjectId("5b08ceb40a8a7614c70a5711"), "name" : "B" }

और अन्य

{
        "_id" : ObjectId("5b08cef10a8a7614c70a5712"),
        "entity" : ObjectId("5b08ceb40a8a7614c70a5710"),
        "name" : "Sub-A"
}
{
        "_id" : ObjectId("5b08cefd0a8a7614c70a5713"),
        "entity" : ObjectId("5b08ceb40a8a7614c70a5711"),
        "name" : "Sub-B"
}

और कुछ वर्गों के लिए उन्हें बाध्य करने के लिए, जैसे कि बहुत ही बुनियादी उदाहरण:

public class Entity
{
  public ObjectId id;
  public string name { get; set; }
}

public class Other
{
  public ObjectId id;
  public ObjectId entity { get; set; }
  public string name { get; set; }
}

public class EntityWithOthers
{
  public ObjectId id;
  public string name { get; set; }
  public IEnumerable<Other> others;
}

 public class EntityWithOther
{
  public ObjectId id;
  public string name { get; set; }
  public Other others;
}

प्रश्न

धाराप्रवाह इंटरफ़ेस

var listNames = new[] { "A", "B" };

var query = entities.Aggregate()
    .Match(p => listNames.Contains(p.name))
    .Lookup(
      foreignCollection: others,
      localField: e => e.id,
      foreignField: f => f.entity,
      @as: (EntityWithOthers eo) => eo.others
    )
    .Project(p => new { p.id, p.name, other = p.others.First() } )
    .Sort(new BsonDocument("other.name",-1))
    .ToList();

सर्वर को अनुरोध भेजा गया:

[
  { "$match" : { "name" : { "$in" : [ "A", "B" ] } } },
  { "$lookup" : { 
    "from" : "others",
    "localField" : "_id",
    "foreignField" : "entity",
    "as" : "others"
  } }, 
  { "$project" : { 
    "id" : "$_id",
    "name" : "$name",
    "other" : { "$arrayElemAt" : [ "$others", 0 ] },
    "_id" : 0
  } },
  { "$sort" : { "other.name" : -1 } }
]

संभवतः समझने में सबसे आसान है क्योंकि धाराप्रवाह इंटरफ़ेस मूल रूप से सामान्य बीएसओएन संरचना के समान है। $lookup मंच में सभी समान तर्क हैं और $arrayElemAt First() . के साथ दर्शाया गया है . $sort . के लिए आप बस एक बीएसओएन दस्तावेज़ या अन्य मान्य अभिव्यक्ति प्रदान कर सकते हैं।

एक विकल्प $lookup . का नया अर्थपूर्ण रूप है MongoDB 3.6 और इसके बाद के संस्करण के लिए उप-पाइपलाइन विवरण के साथ।

BsonArray subpipeline = new BsonArray();

subpipeline.Add(
  new BsonDocument("$match",new BsonDocument(
    "$expr", new BsonDocument(
      "$eq", new BsonArray { "$$entity", "$entity" }  
    )
  ))
);

var lookup = new BsonDocument("$lookup",
  new BsonDocument("from", "others")
    .Add("let", new BsonDocument("entity", "$_id"))
    .Add("pipeline", subpipeline)
    .Add("as","others")
);

var query = entities.Aggregate()
  .Match(p => listNames.Contains(p.name))
  .AppendStage<EntityWithOthers>(lookup)
  .Unwind<EntityWithOthers, EntityWithOther>(p => p.others)
  .SortByDescending(p => p.others.name)
  .ToList();

सर्वर को अनुरोध भेजा गया:

[ 
  { "$match" : { "name" : { "$in" : [ "A", "B" ] } } },
  { "$lookup" : {
    "from" : "others",
    "let" : { "entity" : "$_id" },
    "pipeline" : [
      { "$match" : { "$expr" : { "$eq" : [ "$$entity", "$entity" ] } } }
    ],
    "as" : "others"
  } },
  { "$unwind" : "$others" },
  { "$sort" : { "others.name" : -1 } }
]

धाराप्रवाह "बिल्डर" अभी तक सीधे सिंटैक्स का समर्थन नहीं करता है, न ही LINQ एक्सप्रेशंस $expr का समर्थन करता है ऑपरेटर, हालांकि आप अभी भी BsonDocument . का उपयोग करके निर्माण कर सकते हैं और BsonArray या अन्य मान्य अभिव्यक्तियाँ। यहां हम $unwind . को भी "टाइप" करते हैं एक $sort . लागू करने के लिए परिणाम BsonDocument . के बजाय व्यंजक का उपयोग करना जैसा कि पहले दिखाया गया है।

अन्य उपयोगों के अलावा, "उप-पाइपलाइन" का प्राथमिक कार्य $lookup के लक्ष्य सरणी में लौटाए गए दस्तावेज़ों को कम करना है . साथ ही $unwind यहाँ वास्तव में $lookup . में "विलय" होने का उद्देश्य पूरा करता है सर्वर निष्पादन पर बयान, इसलिए यह आमतौर पर परिणामी सरणी के पहले तत्व को हथियाने की तुलना में अधिक कुशल है।

क्वेरी करने योग्य GroupJoin

var query = entities.AsQueryable()
    .Where(p => listNames.Contains(p.name))
    .GroupJoin(
      others.AsQueryable(),
      p => p.id,
      o => o.entity,
      (p, o) => new { p.id, p.name, other = o.First() }
    )
    .OrderByDescending(p => p.other.name);

सर्वर को अनुरोध भेजा गया:

[ 
  { "$match" : { "name" : { "$in" : [ "A", "B" ] } } },
  { "$lookup" : {
    "from" : "others",
    "localField" : "_id",
    "foreignField" : "entity",
    "as" : "o"
  } },
  { "$project" : {
    "id" : "$_id",
    "name" : "$name",
    "other" : { "$arrayElemAt" : [ "$o", 0 ] },
    "_id" : 0
  } },
  { "$sort" : { "other.name" : -1 } }
]

यह लगभग समान है लेकिन केवल अलग इंटरफ़ेस का उपयोग करता है और थोड़ा अलग बीएसओएन कथन उत्पन्न करता है, और वास्तव में केवल कार्यात्मक बयानों में सरलीकृत नामकरण के कारण। यह केवल $unwind . का उपयोग करने की दूसरी संभावना को सामने लाता है जैसा कि SelectMany() . से तैयार किया गया है :

var query = entities.AsQueryable()
  .Where(p => listNames.Contains(p.name))
  .GroupJoin(
    others.AsQueryable(),
    p => p.id,
    o => o.entity,
    (p, o) => new { p.id, p.name, other = o }
  )
  .SelectMany(p => p.other, (p, other) => new { p.id, p.name, other })
  .OrderByDescending(p => p.other.name);

सर्वर को अनुरोध भेजा गया:

[
  { "$match" : { "name" : { "$in" : [ "A", "B" ] } } },
  { "$lookup" : {
    "from" : "others",
    "localField" : "_id",
    "foreignField" : "entity",
    "as" : "o"
  }},
  { "$project" : {
    "id" : "$_id",
    "name" : "$name",
    "other" : "$o",
    "_id" : 0
  } },
  { "$unwind" : "$other" },
  { "$project" : {
    "id" : "$id",
    "name" : "$name",
    "other" : "$other",
    "_id" : 0
  }},
  { "$sort" : { "other.name" : -1 } }
]

आम तौर पर एक $unwind placing रखना सीधे $lookup . का अनुसरण कर रहे हैं वास्तव में एकत्रीकरण ढांचे के लिए एक "अनुकूलित पैटर्न" है। हालांकि .NET ड्राइवर इस संयोजन में $project . को मजबूर करके इसे गड़बड़ कर देता है बीच में "as" . पर निहित नामकरण का उपयोग करने के बजाय . यदि इसके लिए नहीं, तो यह वास्तव में $arrayElemAt . से बेहतर है जब आप जानते हैं कि आपके पास "एक" संबंधित परिणाम है। अगर आप $unwind चाहते हैं "सहसंयोजन", तो आप धाराप्रवाह इंटरफ़ेस, या बाद में दिखाए गए किसी भिन्न रूप का उपयोग करना बेहतर समझते हैं।

क्वेरेबल नेचुरल

var query = from p in entities.AsQueryable()
            where listNames.Contains(p.name) 
            join o in others.AsQueryable() on p.id equals o.entity into joined
            select new { p.id, p.name, other = joined.First() }
            into p
            orderby p.other.name descending
            select p;

सर्वर को अनुरोध भेजा गया:

[
  { "$match" : { "name" : { "$in" : [ "A", "B" ] } } },
  { "$lookup" : {
    "from" : "others",
    "localField" : "_id",
    "foreignField" : "entity",
    "as" : "joined"
  } },
  { "$project" : {
    "id" : "$_id",
    "name" : "$name",
    "other" : { "$arrayElemAt" : [ "$joined", 0 ] },
    "_id" : 0
  } },
  { "$sort" : { "other.name" : -1 } }
]

सभी बहुत परिचित और वास्तव में कार्यात्मक नामकरण के लिए नीचे। ठीक वैसे ही जैसे $unwind . का उपयोग करने के साथ विकल्प:

var query = from p in entities.AsQueryable()
            where listNames.Contains(p.name) 
            join o in others.AsQueryable() on p.id equals o.entity into joined
            from sub_o in joined.DefaultIfEmpty()
            select new { p.id, p.name, other = sub_o }
            into p
            orderby p.other.name descending
            select p;

सर्वर को अनुरोध भेजा गया:

[ 
  { "$match" : { "name" : { "$in" : [ "A", "B" ] } } },
  { "$lookup" : {
    "from" : "others",
    "localField" : "_id",
    "foreignField" : "entity",
    "as" : "joined"
  } },
  { "$unwind" : { 
    "path" : "$joined", "preserveNullAndEmptyArrays" : true
  } }, 
  { "$project" : { 
    "id" : "$_id",
    "name" : "$name",
    "other" : "$joined",
    "_id" : 0
  } }, 
  { "$sort" : { "other.name" : -1 } }
]

जो वास्तव में "अनुकूलित सहसंयोजन" रूप का उपयोग कर रहा है। अनुवादक अभी भी $project . जोड़ने पर जोर देता है चूंकि हमें इंटरमीडिएट की आवश्यकता है select कथन को वैध बनाने के लिए।

सारांश

तो अनिवार्य रूप से वही परिणाम प्राप्त करने के लिए मूल रूप से एक ही क्वेरी स्टेटमेंट पर पहुंचने के कुछ तरीके हैं। जबकि आप JSON को BsonDocument . में "पार्स" कर सकते हैं फॉर्म करें और इसे धाराप्रवाह Aggregate() . को खिलाएं कमांड, आमतौर पर प्राकृतिक बिल्डरों या LINQ इंटरफेस का उपयोग करना बेहतर होता है क्योंकि वे एक ही स्टेटमेंट पर आसानी से मैप करते हैं।

$unwind . के साथ विकल्प बड़े पैमाने पर दिखाए जाते हैं क्योंकि "एकवचन" मिलान के साथ भी "सहसंयोजन" रूप वास्तव में $arrayElemAt का उपयोग करने से कहीं अधिक इष्टतम है "पहला" सरणी तत्व लेने के लिए। यह बीएसओएन लिमिट जैसी चीजों को ध्यान में रखते हुए और भी महत्वपूर्ण हो जाता है जहां $lookup लक्ष्य सरणी मूल दस्तावेज़ को आगे फ़िल्टर किए बिना 16 एमबी से अधिक का कारण बन सकती है। कुल $lookup पर यहां एक और पोस्ट है मिलान पाइपलाइन में दस्तावेज़ों का कुल आकार अधिकतम दस्तावेज़ आकार से अधिक है जहां मैं वास्तव में चर्चा करता हूं कि ऐसे विकल्पों या अन्य Lookup() का उपयोग करके उस सीमा को हिट होने से कैसे बचा जाए। इस समय केवल धाराप्रवाह इंटरफ़ेस के लिए सिंटैक्स उपलब्ध है।




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. महीने के हिसाब से समूह और गिनती

  2. मोंगो में शार्किंग और प्रतिकृति के बीच अंतर क्या है?

  3. mongoimport के आयात मोड

  4. Node.js, Mongo डेटा ढूंढते हैं और वापस करते हैं

  5. मैंने एक सप्ताह में दायरे और स्विफ्टयूआई के साथ चार्ट-टॉपिंग ऐप कैसे लिखा