Ob একটি অ্যারেতে অবজেক্টআইডের সন্ধান


104

একটি ক্ষেত্রের জন্য কেবলমাত্র একটি একক অবজেক্টআইডি না করে অবজেক্টআইডসের একটি অ্যারে দেখার জন্য বাক্য গঠন কী?

উদাহরণ অর্ডার ডকুমেন্ট:

{
  _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>}
  ],
}

অর্ডার ডকুমেন্ট সহ আমার উদাহরণটি কি যথেষ্ট পরিষ্কার নয়? আপনি পণ্য জন্য উদাহরণ নথি চান?
জেসন লিন

SERVER-22881 প্রত্যাশা অনুযায়ী অ্যারে তৈরির কাজ ট্র্যাক করবে (আক্ষরিক মান হিসাবে নয়)।
অস্যা কামস্কি

উত্তর:


145

2017 আপডেট

$ অনুসন্ধান এখন সরাসরি স্থানীয় ক্ষেত্র হিসাবে একটি অ্যারে ব্যবহার করতে পারে$unwindআর দরকার নেই।

পুরানো উত্তর

$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মূলত যেমনটি খুব নতুন, এটি বর্তমানে মঙ্গুসের সাথে পরিচিত যারা .populate()সেখানে দেওয়া পদ্ধতির "দরিদ্র ম্যানস সংস্করণ" হিসাবে পরিচিত তাদের সাথে কাজ করবে । $lookupক্লায়েন্টের বিপরীতে "জয়েন" এর "সার্ভার সাইড" প্রসেসিংয়ের যে পার্থক্য রয়েছে এবং $lookupবর্তমানে কিছু "পরিপক্কতা" কী .populate()অফারগুলি থেকে অনুপস্থিত রয়েছে (যেমন সরাসরি অ্যারেতে লুকোচুরিকে কেন্দ্র করে)।

এটি প্রকৃতপক্ষে সার্ভার -২২৮১১ এর জন্য একটি নির্ধারিত সমস্যা , সুতরাং কিছু ভাগ্যের সাথে এটি পরবর্তী প্রকাশ বা শীঘ্রই তারপরে আসতে পারে।

ডিজাইনের নীতি হিসাবে, আপনার বর্তমান কাঠামো ভাল বা খারাপ নয়, তবে কোনও "যোগদান" তৈরি করার সময় কেবল ওভারহেডের সাপেক্ষে। যেমন, সূচনাতে মঙ্গোডিবি-র মূল স্থায়ী নীতিটি প্রযোজ্য, যেখানে আপনি যদি একটি সংগ্রহের "প্রাক-যোগদান" ডেটার সাথে "থাকতে" পারেন তবে তা করা ভাল।

$lookupএকটি সাধারণ বিষয় যা সাধারণ নীতি হিসাবে বলা যেতে পারে তা হ'ল এখানে "যোগ দিন" এর অভিপ্রায়টি এখানে দেখানো চেয়ে অন্যভাবে কাজ করা। সুতরাং "প্যারেন্ট" নথির মধ্যে অন্যান্য নথির "সম্পর্কিত আইডিকে" রাখার পরিবর্তে, সাধারণ নীতিটি সবচেয়ে ভাল কাজ করে যেখানে "সম্পর্কিত নথিগুলিতে" পিতামাতার সাথে একটি উল্লেখ রয়েছে।

সুতরাং $lookup"সম্পর্কের নকশা" দিয়ে "সেরা কাজ করতে" বলা যেতে পারে যা মঙ্গুসের মতো কিছু .populate()তার ক্লায়েন্টের সাথে যোগ দেয় তার বিপরীত is পরিবর্তে প্রতিটি "অনেক" এর মধ্যে "এক" আদর্শ করে, তারপরে আপনি $unwindপ্রথমে অ্যারের প্রয়োজন ছাড়াই সম্পর্কিত আইটেমগুলি টানুন ।


ধন্যবাদ এটি কাজ করে! এটি কি এমন একটি সূচক যে আমার ডেটা সঠিকভাবে কাঠামোবদ্ধ / স্বাভাবিক করা হয়নি?
জেসন লিন

4
@ জেসনলিন "ভাল / খারাপ" এর মতো স্ট্রেইগফোরওয়ার্ড নয়, সুতরাং উত্তরে আরও কিছুটা ব্যাখ্যা যুক্ত হয়েছে। এটি আপনার পক্ষে কী উপযুক্ত তা নির্ভর করে।
ব্লেকস সেভেন

4
বর্তমান বাস্তবায়ন কিছুটা অনিচ্ছাকৃত। স্থানীয় ক্ষেত্রের একটি অ্যারেতে সমস্ত মান সন্ধান করা অর্থবোধ করে, এটি অ্যারেটি আক্ষরিকভাবে ব্যবহার করা বোধ করে না তাই সার্ভার -২২৮১১ এটি ঠিক করতে ট্র্যাক করবে।
অস্যা কামস্কি

পছন্দ করেছেন আমি সাধারণত জিজ্ঞাসাবাদের পুনঃস্থাপন $lookupএবং ডকুমেন্টের বৈধতাটিকে তাদের শৈশবস্থানের বৈশিষ্ট্য হিসাবে চিহ্নিত করে এবং সম্ভবত উন্নতি করতে পারি। সুতরাং অ্যারেতে সরাসরি সম্প্রসারণকে স্বাগত জানানো হবে, ফলাফলগুলি ফিল্টার করার জন্য "কোয়েরি" হবে। এই দু'টিই .populate()অনেকগুলি ব্যবহৃত মঙ্গস প্রক্রিয়াটির সাথে আরও অনেকগুলি সংযুক্ত হবে। উত্তরের সামগ্রীটিতে ইস্যুটির লিঙ্কটি সরাসরি যুক্ত করা হচ্ছে।
ব্লেকস সেভেন

4
মনে রাখবেন যে এর নীচের উত্তর অনুসারে, এটি এখন বাস্তবায়িত হয়েছে এবং $lookupএখন সরাসরি অ্যারেতে কাজ করে।
অ্যাডাম রেইস


15

আপনি pipelineসাব-ডকুমেন্ট অ্যারেতে চেক সঞ্চালনের জন্য মঞ্চটি ব্যবহার করতে পারেন

উদাহরণটি এখানে ব্যবহার করে python(দুঃখিত আমি সাপ মানুষ)।

db.products.aggregate([
  { '$lookup': {
      'from': 'products',
      'let': { 'pid': '$products' },
      'pipeline': [
        { '$match': { '$expr': { '$in': ['$_id', '$$pid'] } } }
        // Add additional stages here 
      ],
      'as':'productObjects'
  }
])

এখানে ধরাটি হ'ল ObjectId array(বিদেশী _idযা localক্ষেত্র / প্রপোসে রয়েছে products) সমস্ত বস্তুর সাথে মেলে ।

stageউপরের মন্তব্যে নির্দেশিত হিসাবে আপনি অতিরিক্ত বা বিদেশী রেকর্ডগুলি পরিষ্কার বা প্রজেক্ট করতে পারেন ।


4

unwind ব্যবহার করুন আপনি বস্তুর অ্যারের পরিবর্তে প্রথম অবজেক্টটি পাবেন

প্রশ্ন:

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"
    }
}

0

সঙ্গে, সঞ্চিত $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")
    ...

0

আমার একমত হতে হবে না, আমরা যদি $ ম্যাচ পর্যায়ে এটির উপস্থাপন করি তবে আমরা আইডি অ্যারে দিয়ে $ দেখার কাজটি করতে পারি।

// replace IDs array with lookup results
db.products.aggregate([
    { $match: { products : { $exists: true } } },
    {
        $lookup: {
            from: "products",
            localField: "products",
            foreignField: "_id",
            as: "productObjects"
        }
    }
])

আমরা যদি ফলাফলের ফলাফলটি পাইপলাইনে পাস করতে চাই তবে এটি আরও জটিল হয়ে যায়। তবে তারপরে আবারও এটি করার একটি উপায় রয়েছে (ইতিমধ্যে @ ব্যবহারকারী 12164 দ্বারা প্রস্তাবিত):

// replace IDs array with lookup results passed to pipeline
db.products.aggregate([
    { $match: { products : { $exists: true } } },
    {
        $lookup: {
            from: "products",
             let: { products: "$products"},
             pipeline: [
                 { $match: { $expr: {$in: ["$_id", "$$products"] } } },
                 { $project: {_id: 0} } // suppress _id
             ],
            as: "productObjects"
        }
    }
])

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.