2016-01-23 4 views
37

एक ऐसे ऑब्जेक्ट पर $ लुकअप करने के लिए वाक्यविन्यास क्या है जो केवल एक ऑब्जेक्ट आईडी के बजाय ऑब्जेक्ट आईडी की सरणी है?ऑब्जेक्टआईड पर ऑब्जेक्टआईड पर एक लुकअप

उदाहरण आदेश दस्तावेज़:

{ 
    _id: ObjectId("..."), 
    products: [ 
    ObjectId("..<Car ObjectId>.."), 
    ObjectId("..<Bike ObjectId>..") 
    ] 
} 

काम नहीं कर रहा क्वेरी:

db.orders.aggregate([ 
    { 
     $lookup: 
     { 
      from: "products", 
      localField: "products", 
      foreignField: "_id", 
      as: "productObjects" 
     } 
    } 
]) 

वांछित परिणाम

{ 
    _id: ObjectId("..."), 
    products: [ 
    ObjectId("..<Car ObjectId>.."), 
    ObjectId("..<Bike ObjectId>..") 
    ], 
    productObjects: [ 
    {<Car Object>}, 
    {<Bike Object>} 
    ], 
} 
+0

आदेश दस्तावेज़ पर्याप्त स्पष्ट नहीं के साथ अपने उदाहरण है? क्या आप उत्पादों के लिए उदाहरण दस्तावेज चाहते हैं? –

+0

सेवर -22881 सरणी कार्य को अपेक्षित बनाने के रूप में ट्रैक करेगा (एक शाब्दिक मूल्य के रूप में नहीं)। –

उत्तर

63

$lookup एकत्रीकरण पाइपलाइन चरण एक सरणी के साथ सीधे काम नहीं करेगा। डिज़ाइन का मुख्य उद्देश्य संभावित संबंधित डेटा पर "बाएं शामिल" के लिए "एक से कई" प्रकार के जुड़ने के लिए है (या वास्तव में "लुकअप") के लिए है। लेकिन मूल्य एकवचन और एक सरणी नहीं है।

इसलिए आपको काम करने के लिए $lookup ऑपरेशन करने से पहले सामग्री को "डी-सामान्य" करना होगा। और वह $unwind का उपयोग कर का अर्थ है: प्रत्येक सरणी सदस्य परिणाम एक सरणी ही है

db.orders.aggregate([ 
    // Unwind the source 
    { "$unwind": "$products" }, 
    // Do the lookup matching 
    { "$lookup": { 
     "from": "products", 
     "localField": "products", 
     "foreignField": "_id", 
     "as": "productObjects" 
    }}, 
    // Unwind the result arrays (likely one or none) 
    { "$unwind": "$productObjects" }, 
    // Group back to arrays 
    { "$group": { 
     "_id": "$_id", 
     "products": { "$push": "$products" }, 
     "productObjects": { "$push": "$productObjects" } 
    }} 
]) 

$lookup के बाद मैच, ताकि आप फिर $unwind और अंतिम परिणाम के लिए $group$push करने के लिए नए सरणियों।

ध्यान दें कि कोई भी "बाएं शामिल" मिलान नहीं मिला है जो दिए गए उत्पाद पर "productObjects" के लिए एक खाली सरणी बनाएगा और इस प्रकार "उत्पाद" तत्व के लिए दस्तावेज़ को अस्वीकार कर देगा जब दूसरा $unwind कहा जाता है।

हालांकि एक सरणी के लिए एक सीधा अनुप्रयोग अच्छा होगा, लेकिन यह वर्तमान में एक संभावित मूल्य के साथ एकवचन मूल्य से मेल खाता है।

$lookup के रूप में मूल रूप से यह वर्तमान में जो लोग mongoose.populate() विधि वहाँ की पेशकश की एक "गरीब मनुष्य संस्करण" के रूप में के साथ परिचित हैं के लिए परिचित हो जाएगा के रूप में काम करता है बिल्कुल नई है,। अंतर यह है कि $lookup क्लाइंट के विरोध में "शामिल" की "सर्वर साइड" प्रसंस्करण प्रदान करता है और $lookup में "परिपक्वता" में से कुछ वर्तमान में .populate() ऑफ़र (जैसे कि सरणी पर सीधे लुकअप को इंटरपोल करना) की कमी है। ।

यह वास्तव में SERVER-22881 में सुधार के लिए एक असाइन किया गया मुद्दा है, इसलिए कुछ भाग्य के साथ यह अगली रिलीज या जल्द ही बाद में होगा।

एक डिजाइन सिद्धांत के रूप में, आपकी वर्तमान संरचना न तो अच्छी या बुरी है, लेकिन किसी भी "शामिल" बनाते समय ओवरहेड के अधीन है। इस प्रकार, आरंभ में मोंगोडीबी का मूल स्थायी सिद्धांत लागू होता है, जहां आप एक संग्रह में "पूर्व-जुड़े" डेटा के साथ "रह सकते हैं", तो ऐसा करना सबसे अच्छा है।

एक अन्य बात जिसे $lookup के सामान्य सिद्धांत के रूप में कहा जा सकता है, यह है कि यहां "शामिल" का इरादा यहां दिखाए जाने के अलावा अन्य तरीकों से काम करना है। इसलिए "मूल" दस्तावेज़ के भीतर अन्य दस्तावेजों के "संबंधित आईडी" को रखने के बजाय, सामान्य सिद्धांत जो सर्वोत्तम कार्य करता है वह है जहां "संबंधित दस्तावेज़" में "पैरेंट" का संदर्भ होता है।

तो $lookup को "रिलेशनशिप डिज़ाइन" के साथ "सर्वश्रेष्ठ काम" करने के लिए कहा जा सकता है, जो कि मॉन्गोज .populate() जैसे कुछ क्लाइंट पक्ष में शामिल होता है, इसके विपरीत है। इसके बजाय प्रत्येक "कई" में "एक" को निष्क्रिय करके, फिर आप पहले से ही $unwind सरणी की आवश्यकता के बिना संबंधित आइटम खींचें।

+0

धन्यवाद यह काम करता है! क्या यह एक संकेतक है कि मेरा डेटा ठीक से संरचित/सामान्यीकृत नहीं है? –

+1

@JasonLin "अच्छा/बुरा" के रूप में straigtforward के रूप में नहीं, तो जवाब में थोड़ा और व्याख्या जोड़ा गया है। यह इस बात पर निर्भर करता है कि आप क्या सूट करते हैं। –

+2

वर्तमान कार्यान्वयन कुछ हद तक अनजान है। स्थानीय क्षेत्र की सरणी में सभी मानों को देखने के लिए यह समझ में आता है, यह सचमुच सरणी का उपयोग करने के लिए समझ में नहीं आता है इसलिए SERVER-22881 उस फिक्सिंग को ट्रैक करेगा। –

27

$lookup एकत्रीकरण पाइपलाइन चरण अब सीधे एक सरणी के साथ काम करता है ( 3.3.4 संस्करण पर)।

देखें: lookup between local (multiple)array of values and foreign (single) value

+0

धन्यवाद यह मेरा जीवन आसान बनाता है – vaibhavmaster

+1

कोई काम नहीं कर रहा है! अभी भी मुझे एक ही समस्या है –

-1

$lookup साथ एकीकृत करने वाला और बाद $group बहुत बोझिल है, इसलिए यदि (और है कि अगर एक माध्यम है) आप नोड & का उपयोग कर रहे नेवला या स्कीमा, आप कर सकते थे में कुछ संकेत के साथ एक सहायक पुस्तकालय एक .populate() का उपयोग उन दस्तावेजों को लाने के लिए:

var mongoose = require("mongoose"), 
    Schema = mongoose.Schema; 

var productSchema = Schema({ ... }); 

var orderSchema = Schema({ 
    _id  : Number, 
    products: [ { type: Schema.Types.ObjectId, ref: "Product" } ] 
}); 

var Product = mongoose.model("Product", productSchema); 
var Order = mongoose.model("Order", orderSchema); 

... 

Order 
    .find(...) 
    .populate("products") 
    ... 
1

उपयोग $ तनाव कम आप वस्तुओं

की सरणी के बजाय पहली वस्तु मिल जाएगा

क्वेरी:

db.getCollection('vehicles').aggregate([ 
    { 
    $match: { 
     status: "AVAILABLE", 
     vehicleTypeId: { 
     $in: Array.from(newSet(d.vehicleTypeIds)) 
     } 
    } 
    }, 
    { 
    $lookup: { 
     from: "servicelocations", 
     localField: "locationId", 
     foreignField: "serviceLocationId", 
     as: "locations" 
    } 
    }, 
    { 
    $unwind: "$locations" 
    } 
]); 

परिणाम:

{ 
    "_id" : ObjectId("59c3983a647101ec58ddcf90"), 
    "vehicleId" : "45680", 
    "regionId" : 1.0, 
    "vehicleTypeId" : "10TONBOX", 
    "locationId" : "100", 
    "description" : "Isuzu/2003-10 Ton/Box", 
    "deviceId" : "", 
    "earliestStart" : 36000.0, 
    "latestArrival" : 54000.0, 
    "status" : "AVAILABLE", 
    "accountId" : 1.0, 
    "locations" : { 
     "_id" : ObjectId("59c3afeab7799c90ebb3291f"), 
     "serviceLocationId" : "100", 
     "regionId" : 1.0, 
     "zoneId" : "DXBZONE1", 
     "description" : "Masafi Park Al Quoz", 
     "locationPriority" : 1.0, 
     "accountTypeId" : 0.0, 
     "locationType" : "DEPOT", 
     "location" : { 
      "makani" : "", 
      "lat" : 25.123091, 
      "lng" : 55.21082 
     }, 
     "deliveryDays" : "MTWRFSU", 
     "timeWindow" : { 
      "timeWindowTypeId" : "1" 
     }, 
     "address1" : "", 
     "address2" : "", 
     "phone" : "", 
     "city" : "", 
     "county" : "", 
     "state" : "", 
     "country" : "", 
     "zipcode" : "", 
     "imageUrl" : "", 
     "contact" : { 
      "name" : "", 
      "email" : "" 
     }, 
     "status" : "", 
     "createdBy" : "", 
     "updatedBy" : "", 
     "updateDate" : "", 
     "accountId" : 1.0, 
     "serviceTimeTypeId" : "1" 
    } 
} 


{ 
    "_id" : ObjectId("59c3983a647101ec58ddcf91"), 
    "vehicleId" : "81765", 
    "regionId" : 1.0, 
    "vehicleTypeId" : "10TONBOX", 
    "locationId" : "100", 
    "description" : "Hino/2004-10 Ton/Box", 
    "deviceId" : "", 
    "earliestStart" : 36000.0, 
    "latestArrival" : 54000.0, 
    "status" : "AVAILABLE", 
    "accountId" : 1.0, 
    "locations" : { 
     "_id" : ObjectId("59c3afeab7799c90ebb3291f"), 
     "serviceLocationId" : "100", 
     "regionId" : 1.0, 
     "zoneId" : "DXBZONE1", 
     "description" : "Masafi Park Al Quoz", 
     "locationPriority" : 1.0, 
     "accountTypeId" : 0.0, 
     "locationType" : "DEPOT", 
     "location" : { 
      "makani" : "", 
      "lat" : 25.123091, 
      "lng" : 55.21082 
     }, 
     "deliveryDays" : "MTWRFSU", 
     "timeWindow" : { 
      "timeWindowTypeId" : "1" 
     }, 
     "address1" : "", 
     "address2" : "", 
     "phone" : "", 
     "city" : "", 
     "county" : "", 
     "state" : "", 
     "country" : "", 
     "zipcode" : "", 
     "imageUrl" : "", 
     "contact" : { 
      "name" : "", 
      "email" : "" 
     }, 
     "status" : "", 
     "createdBy" : "", 
     "updatedBy" : "", 
     "updateDate" : "", 
     "accountId" : 1.0, 
     "serviceTimeTypeId" : "1" 
    } 
} 
संबंधित मुद्दे