Mongoose में आबाद होने के बाद क्वेरी


83

मैं मानसून और MongoDB के लिए सामान्य रूप से बहुत नया हूं, इसलिए मुझे यह पता लगाने में मुश्किल समय आ रहा है कि ऐसा कुछ संभव है:

Item = new Schema({
    id: Schema.ObjectId,
    dateCreated: { type: Date, default: Date.now },
    title: { type: String, default: 'No Title' },
    description: { type: String, default: 'No Description' },
    tags: [ { type: Schema.ObjectId, ref: 'ItemTag' }]
});

ItemTag = new Schema({
    id: Schema.ObjectId,
    tagId: { type: Schema.ObjectId, ref: 'Tag' },
    tagName: { type: String }
});



var query = Models.Item.find({});

query
    .desc('dateCreated')
    .populate('tags')
    .where('tags.tagName').in(['funny', 'politics'])
    .run(function(err, docs){
       // docs is always empty
    });

क्या ऐसा करने का एक बेहतर तरीका है?

संपादित करें

किसी भी भ्रम के लिए क्षमा याचना। मैं जो करने की कोशिश कर रहा हूं वह सभी आइटमों को मिलता है जिसमें या तो मजेदार टैग या राजनीति टैग होता है।

संपादित करें

दस्तावेज़ जहाँ खंड के बिना:

[{ 
    _id: 4fe90264e5caa33f04000012,
    dislikes: 0,
    likes: 0,
    source: '/uploads/loldog.jpg',
    comments: [],
    tags: [{
        itemId: 4fe90264e5caa33f04000012,
        tagName: 'movies',
        tagId: 4fe64219007e20e644000007,
        _id: 4fe90270e5caa33f04000015,
        dateCreated: Tue, 26 Jun 2012 00:29:36 GMT,
        rating: 0,
        dislikes: 0,
        likes: 0 
    },
    { 
        itemId: 4fe90264e5caa33f04000012,
        tagName: 'funny',
        tagId: 4fe64219007e20e644000002,
        _id: 4fe90270e5caa33f04000017,
        dateCreated: Tue, 26 Jun 2012 00:29:36 GMT,
        rating: 0,
        dislikes: 0,
        likes: 0 
    }],
    viewCount: 0,
    rating: 0,
    type: 'image',
    description: null,
    title: 'dogggg',
    dateCreated: Tue, 26 Jun 2012 00:29:24 GMT 
 }, ... ]

जहां क्लॉज के साथ, मुझे एक खाली एरे मिलता है।

जवाबों:


61

3.2 से अधिक एक आधुनिक MongoDB के साथ आप ज्यादातर मामलों में $lookupवैकल्पिक के रूप में उपयोग कर सकते हैं .populate()। यह भी वास्तव में "सर्वर पर" के रूप में शामिल होने का विरोध किया गया .populate()है, जो कि वास्तव में "एकाधिक प्रश्न" में शामिल होने के लिए "अनुकरण" करने का विरोध करता है ।

तो .populate()है नहीं वास्तव में "शामिल हों" कैसे एक संबंधपरक डेटाबेस यह करता है के तौर पर। $lookupदूसरी ओर ऑपरेटर, वास्तव में सर्वर पर काम करता है, और अधिक या कम एक के अनुरूप है "वाम शामिल हों" :

Item.aggregate(
  [
    { "$lookup": {
      "from": ItemTags.collection.name,
      "localField": "tags",
      "foreignField": "_id",
      "as": "tags"
    }},
    { "$unwind": "$tags" },
    { "$match": { "tags.tagName": { "$in": [ "funny", "politics" ] } } },
    { "$group": {
      "_id": "$_id",
      "dateCreated": { "$first": "$dateCreated" },
      "title": { "$first": "$title" },
      "description": { "$first": "$description" },
      "tags": { "$push": "$tags" }
    }}
  ],
  function(err, result) {
    // "tags" is now filtered by condition and "joined"
  }
)

नायब.collection.name यहाँ वास्तव में "स्ट्रिंग" के रूप में मॉडल करने के लिए सौंपा MongoDB संग्रह का वास्तविक नाम है कि करने के लिए मूल्यांकन करता है। चूंकि mongoose डिफ़ॉल्ट रूप से "संग्रह नाम" का बहुवचन करता है और $lookupउसे एक तर्क के रूप में वास्तविक MongoDB संग्रह नाम की आवश्यकता होती है (क्योंकि यह एक सर्वर ऑपरेशन है), तो यह mongoose कोड में उपयोग करने के लिए एक आसान ट्रिक है, जैसा कि सीधे "हार्ड कोडिंग" संग्रह नाम के विपरीत है। ।

वैसे तो हम भी इस्तेमाल कर सकते हैं $filterसरणियों पर अवांछित आइटम हटाने के लिए, यह वास्तव में की वजह से सबसे कारगर तरीका है एकत्रीकरण पाइपलाइन अनुकूलन के रूप में की विशेष स्थिति के लिए $lookupदोनों एक के बाद $unwindऔर एक$match शर्त के बाद।

यह वास्तव में तीन पाइपलाइन चरणों को एक में लुढ़का देता है:

   { "$lookup" : {
     "from" : "itemtags",
     "as" : "tags",
     "localField" : "tags",
     "foreignField" : "_id",
     "unwinding" : {
       "preserveNullAndEmptyArrays" : false
     },
     "matching" : {
       "tagName" : {
         "$in" : [
           "funny",
           "politics"
         ]
       }
     }
   }}

यह अत्यधिक इष्टतम है क्योंकि वास्तविक ऑपरेशन "पहले शामिल होने के लिए संग्रह को फ़िल्टर करता है", फिर यह परिणाम लौटाता है और सरणी को "अनइंड्स" करता है। दोनों विधियों को नियोजित किया जाता है, इसलिए परिणाम 16MB की BSON सीमा को नहीं तोड़ते हैं, जो एक बाधा है जो क्लाइंट के पास नहीं है।

एकमात्र समस्या यह है कि यह कुछ तरीकों से "काउंटर-सहज" लगता है, खासकर जब आप किसी सरणी में परिणाम चाहते हैं, लेकिन यह वही है जो $groupयहां के लिए है, क्योंकि यह मूल दस्तावेज़ फ़ॉर्म में पुनर्निर्माण करता है।

यह भी दुर्भाग्यपूर्ण है कि हम इस समय वास्तव $lookupमें उसी क्रमिक सिंटैक्स में नहीं लिख सकते जो सर्वर उपयोग करता है। IMHO, यह सही होने के लिए एक निरीक्षण है। लेकिन अभी के लिए, केवल अनुक्रम का उपयोग करना काम करेगा और सबसे अच्छा प्रदर्शन और मापनीयता के साथ सबसे व्यवहार्य विकल्प है।

परिशिष्ट - MongoDB 3.6 और ऊपर की ओर

यद्यपि यहां दिखाया गया पैटर्न अन्य चरणों में लुढ़का हुआ होने के कारण काफी अनुकूलित है $lookup, लेकिन इसमें कोई भी ऐसा नहीं है जो "LEFT JOIN" है जो आम तौर पर दोनों के लिए अंतर्निहित है $lookupऔर क्रियाओं populate()को "इष्टतम" उपयोग द्वारा नकार दिया जाता है $unwindयहाँ जो खाली सरणियों को संरक्षित नहीं करता है। आप preserveNullAndEmptyArraysविकल्प जोड़ सकते हैं , लेकिन यह ऊपर वर्णित "अनुकूलित" अनुक्रम को नकार देता है और अनिवार्य रूप से सभी तीन चरणों को बरकरार रखता है जो सामान्य रूप से अनुकूलन में जोड़ा जाएगा।

MongoDB 3.6 "उप-पाइपलाइन" अभिव्यक्ति की अनुमति देने के "अधिक अभिव्यंजक" रूप के साथ फैलता है $lookup। जो न केवल "LEFT JOIN" को बरकरार रखने के लक्ष्य को पूरा करता है, बल्कि फिर भी लौटे हुए परिणामों को कम करने और एक बहुत ही सरल वाक्य रचना के साथ एक इष्टतम क्वेरी की अनुमति देता है:

Item.aggregate([
  { "$lookup": {
    "from": ItemTags.collection.name,
    "let": { "tags": "$tags" },
    "pipeline": [
      { "$match": {
        "tags": { "$in": [ "politics", "funny" ] },
        "$expr": { "$in": [ "$_id", "$$tags" ] }
      }}
    ]
  }}
])

$exprआदेश से मिलान करने में प्रयोग किया जाता घोषित "विदेशी" मूल्य के साथ "स्थानीय" मूल्य वास्तव में क्या MongoDB करता है "आंतरिक" अब मूल के साथ है $lookupवाक्य रचना। इस रूप में व्यक्त करके हम प्रारंभिक $matchअभिव्यक्ति "उप-पाइपलाइन" के भीतर खुद को दर्जी कर सकते हैं।

वास्तव में, एक सच्चे "एकत्रीकरण पाइपलाइन" के रूप में आप इस "उप-पाइपलाइन" अभिव्यक्ति के भीतर एकत्रीकरण पाइपलाइन के साथ कुछ भी कर सकते हैं, जिसमें "घोंसले के शिकार" शामिल हैं $lookup संबंधित अन्य संबंधित संग्रह ।

आगे का उपयोग इस सवाल के दायरे से थोड़ा सा अधिक है, लेकिन यहां तक ​​कि "नेस्टेड आबादी" के संबंध में भी, तो नया उपयोग पैटर्न $lookupइसे बहुत समान करने की अनुमति देता है, और इसमें "बहुत" पूर्ण उपयोग में अधिक शक्तिशाली है।


काम करने का उदाहरण

निम्नलिखित मॉडल पर एक स्थिर विधि का उपयोग करके एक उदाहरण देता है। एक बार उस स्थैतिक विधि को लागू करने के बाद कॉल सरल हो जाती है:

  Item.lookup(
    {
      path: 'tags',
      query: { 'tags.tagName' : { '$in': [ 'funny', 'politics' ] } }
    },
    callback
  )

या थोड़ा और अधिक आधुनिक बनने के लिए बढ़ाना:

  let results = await Item.lookup({
    path: 'tags',
    query: { 'tagName' : { '$in': [ 'funny', 'politics' ] } }
  })

के समान बनाना .populate() संरचना में , लेकिन यह वास्तव में इसके बजाय सर्वर पर शामिल हो रहा है। पूर्णता के लिए, यहाँ उपयोग माता-पिता और बच्चे दोनों के मामलों के अनुसार दस्तावेज़ों के उदाहरणों के लिए डेटा वापस लौटाता है।

यह काफी तुच्छ और आसान है या ज्यादातर सामान्य मामलों के लिए उपयोग करने के लिए आसान है।

नायब यहाँ async का उपयोग केवल संलग्न उदाहरण को चलाने की संक्षिप्तता के लिए है। वास्तविक कार्यान्वयन इस निर्भरता से मुक्त है।

const async = require('async'),
      mongoose = require('mongoose'),
      Schema = mongoose.Schema;

mongoose.Promise = global.Promise;
mongoose.set('debug', true);
mongoose.connect('mongodb://localhost/looktest');

const itemTagSchema = new Schema({
  tagName: String
});

const itemSchema = new Schema({
  dateCreated: { type: Date, default: Date.now },
  title: String,
  description: String,
  tags: [{ type: Schema.Types.ObjectId, ref: 'ItemTag' }]
});

itemSchema.statics.lookup = function(opt,callback) {
  let rel =
    mongoose.model(this.schema.path(opt.path).caster.options.ref);

  let group = { "$group": { } };
  this.schema.eachPath(p =>
    group.$group[p] = (p === "_id") ? "$_id" :
      (p === opt.path) ? { "$push": `$${p}` } : { "$first": `$${p}` });

  let pipeline = [
    { "$lookup": {
      "from": rel.collection.name,
      "as": opt.path,
      "localField": opt.path,
      "foreignField": "_id"
    }},
    { "$unwind": `$${opt.path}` },
    { "$match": opt.query },
    group
  ];

  this.aggregate(pipeline,(err,result) => {
    if (err) callback(err);
    result = result.map(m => {
      m[opt.path] = m[opt.path].map(r => rel(r));
      return this(m);
    });
    callback(err,result);
  });
}

const Item = mongoose.model('Item', itemSchema);
const ItemTag = mongoose.model('ItemTag', itemTagSchema);

function log(body) {
  console.log(JSON.stringify(body, undefined, 2))
}
async.series(
  [
    // Clean data
    (callback) => async.each(mongoose.models,(model,callback) =>
      model.remove({},callback),callback),

    // Create tags and items
    (callback) =>
      async.waterfall(
        [
          (callback) =>
            ItemTag.create([{ "tagName": "movies" }, { "tagName": "funny" }],
              callback),

          (tags, callback) =>
            Item.create({ "title": "Something","description": "An item",
              "tags": tags },callback)
        ],
        callback
      ),

    // Query with our static
    (callback) =>
      Item.lookup(
        {
          path: 'tags',
          query: { 'tags.tagName' : { '$in': [ 'funny', 'politics' ] } }
        },
        callback
      )
  ],
  (err,results) => {
    if (err) throw err;
    let result = results.pop();
    log(result);
    mongoose.disconnect();
  }
)

या नोड 8.x और उससे अधिक के लिए थोड़ा आधुनिक async/awaitऔर कोई अतिरिक्त निर्भरता नहीं:

const { Schema } = mongoose = require('mongoose');
const uri = 'mongodb://localhost/looktest';

mongoose.Promise = global.Promise;
mongoose.set('debug', true);

const itemTagSchema = new Schema({
  tagName: String
});

const itemSchema = new Schema({
  dateCreated: { type: Date, default: Date.now },
  title: String,
  description: String,
  tags: [{ type: Schema.Types.ObjectId, ref: 'ItemTag' }]
});

itemSchema.statics.lookup = function(opt) {
  let rel =
    mongoose.model(this.schema.path(opt.path).caster.options.ref);

  let group = { "$group": { } };
  this.schema.eachPath(p =>
    group.$group[p] = (p === "_id") ? "$_id" :
      (p === opt.path) ? { "$push": `$${p}` } : { "$first": `$${p}` });

  let pipeline = [
    { "$lookup": {
      "from": rel.collection.name,
      "as": opt.path,
      "localField": opt.path,
      "foreignField": "_id"
    }},
    { "$unwind": `$${opt.path}` },
    { "$match": opt.query },
    group
  ];

  return this.aggregate(pipeline).exec().then(r => r.map(m => 
    this({ ...m, [opt.path]: m[opt.path].map(r => rel(r)) })
  ));
}

const Item = mongoose.model('Item', itemSchema);
const ItemTag = mongoose.model('ItemTag', itemTagSchema);

const log = body => console.log(JSON.stringify(body, undefined, 2));

(async function() {
  try {

    const conn = await mongoose.connect(uri);

    // Clean data
    await Promise.all(Object.entries(conn.models).map(([k,m]) => m.remove()));

    // Create tags and items
    const tags = await ItemTag.create(
      ["movies", "funny"].map(tagName =>({ tagName }))
    );
    const item = await Item.create({ 
      "title": "Something",
      "description": "An item",
      tags 
    });

    // Query with our static
    const result = (await Item.lookup({
      path: 'tags',
      query: { 'tags.tagName' : { '$in': [ 'funny', 'politics' ] } }
    })).pop();
    log(result);

    mongoose.disconnect();

  } catch (e) {
    console.error(e);
  } finally {
    process.exit()
  }
})()

और MongoDB 3.6 और ऊपर से, बिना $unwindऔर $groupभवन के भी:

const { Schema, Types: { ObjectId } } = mongoose = require('mongoose');

const uri = 'mongodb://localhost/looktest';

mongoose.Promise = global.Promise;
mongoose.set('debug', true);

const itemTagSchema = new Schema({
  tagName: String
});

const itemSchema = new Schema({
  title: String,
  description: String,
  tags: [{ type: Schema.Types.ObjectId, ref: 'ItemTag' }]
},{ timestamps: true });

itemSchema.statics.lookup = function({ path, query }) {
  let rel =
    mongoose.model(this.schema.path(path).caster.options.ref);

  // MongoDB 3.6 and up $lookup with sub-pipeline
  let pipeline = [
    { "$lookup": {
      "from": rel.collection.name,
      "as": path,
      "let": { [path]: `$${path}` },
      "pipeline": [
        { "$match": {
          ...query,
          "$expr": { "$in": [ "$_id", `$$${path}` ] }
        }}
      ]
    }}
  ];

  return this.aggregate(pipeline).exec().then(r => r.map(m =>
    this({ ...m, [path]: m[path].map(r => rel(r)) })
  ));
};

const Item = mongoose.model('Item', itemSchema);
const ItemTag = mongoose.model('ItemTag', itemTagSchema);

const log = body => console.log(JSON.stringify(body, undefined, 2));

(async function() {

  try {

    const conn = await mongoose.connect(uri);

    // Clean data
    await Promise.all(Object.entries(conn.models).map(([k,m]) => m.remove()));

    // Create tags and items
    const tags = await ItemTag.insertMany(
      ["movies", "funny"].map(tagName => ({ tagName }))
    );

    const item = await Item.create({
      "title": "Something",
      "description": "An item",
      tags
    });

    // Query with our static
    let result = (await Item.lookup({
      path: 'tags',
      query: { 'tagName': { '$in': [ 'funny', 'politics' ] } }
    })).pop();
    log(result);


    await mongoose.disconnect();

  } catch(e) {
    console.error(e)
  } finally {
    process.exit()
  }

})()

3
मैं अब Mongo / Mongoose का उपयोग नहीं कर रहा हूं, लेकिन मैंने आपका उत्तर स्वीकार कर लिया है क्योंकि यह एक लोकप्रिय प्रश्न है और ऐसा लगता है कि यह दूसरों के लिए उपयोगी है। खुशी है कि इस समस्या को देखने के लिए अब और अधिक स्केलेबल समाधान है। अद्यतन उत्तर देने के लिए धन्यवाद।
jschr

40

जो आप पूछ रहे हैं वह सीधे समर्थित नहीं है, लेकिन क्वेरी रिटर्न के बाद एक और फ़िल्टर चरण जोड़कर प्राप्त किया जा सकता है।

सबसे पहले, .populate( 'tags', null, { tagName: { $in: ['funny', 'politics'] } } )निश्चित रूप से आपको टैग दस्तावेज़ों को फ़िल्टर करने के लिए क्या करने की आवश्यकता है। फिर, क्वेरी रिटर्न के बाद, आपको मैन्युअल रूप से उन दस्तावेज़ों को फ़िल्टर करने की आवश्यकता होगी जिनके पास कोई tagsडॉक्स नहीं है जो आबादी के मानदंडों से मेल खाते हैं। कुछ इस तरह:

query....
.exec(function(err, docs){
   docs = docs.filter(function(doc){
     return doc.tags.length;
   })
   // do stuff with docs
});

1
हे हारून, उत्तर के लिए धन्यवाद। मैं गलत हो सकता हूं, लेकिन $ मेल नहीं करेगा () केवल मिलान किए गए टैगों को आबाद करेगा? तो आइटम पर कोई अतिरिक्त टैग फ़िल्टर से बाहर हो जाएगा। ऐसा लगता है कि मुझे सभी आइटमों को पॉप्युलेट करना होगा और दूसरा फ़िल्टर स्टेप इसे टैग नाम के आधार पर कम करना होगा।
jschr

@ARonheckmann मैंने आपके सुझाए गए समाधान को लागू कर दिया है, आप .exec के बाद फ़िल्टर करने के बारे में सही हैं, क्योंकि यद्यपि क्वेरी क्वेरी केवल आवश्यक ऑब्जेक्ट्स को पॉप्युलेट कर रही है, लेकिन फिर भी इसका पूरा डेटा सेट वापस आ रहा है। क्या आप मानगो के नए संस्करण में सोचते हैं कि केवल आबादी वाले डेटा सेट को वापस करने का कोई विकल्प है इसलिए हमें दूसरे फ़िल्टरिंग के लिए जाने की आवश्यकता नहीं है?
अकीब मुमताज

Im प्रदर्शन के बारे में जानने के लिए उत्सुक है, यदि क्वेरी अंत में संपूर्ण डेटासेट लौटा रही है, तो जनसंख्या फ़िल्टरिंग के लिए जाने का कोई उद्देश्य नहीं है? क्यों भाई क्या कहते हो? प्रदर्शन अनुकूलन के लिए आई एम एडाप्टिंग जनसंख्या क्वेरी लेकिन इस तरह से प्रदर्शन बड़े डेटासेट के लिए बेहतर नहीं होगा?
अकीब मुमताज

mongoosejs.com/docs/api.html#query_Query-pulate में सभी विवरण हैं यदि किसी और को दिलचस्पी है
samazi

जब आबादी अलग-अलग क्षेत्रों में कैसे मेल खाती है?
निकोगाल्डो

20

बदलने का प्रयास करें

.populate('tags').where('tags.tagName').in(['funny', 'politics']) 

द्वारा

.populate( 'tags', null, { tagName: { $in: ['funny', 'politics'] } } )

1
उत्तर के लिए धन्यवाद। मेरा मानना ​​है कि यह क्या करता है केवल प्रत्येक आइटम को मजाकिया या राजनीति के साथ आबाद करता है, जो मूल सूची को कम नहीं करेगा। मैं वास्तव में क्या पसंद करूंगा जो केवल आइटम हैं जो उनके टैग में मजाकिया या राजनीति करते हैं।
jschr

क्या आप दिखा सकते हैं कि आपका दस्तावेज़ कैसा दिखता है? Coz एक 'जहां' टैग सरणी के अंदर मुझे एक वैध संचालन की तरह लगता है..क्या हम सिर्फ वाक्यविन्यास गलत कर रहे हैं..क्या आपने उस 'को हटाने की कोशिश की' जहां पूरी तरह से खंड और जाँच की कि क्या कुछ भी वापस आ गया है? वैकल्पिक रूप से, केवल यह जांचने के लिए कि क्या 'टैग्सटैगनाम' लिखना वाक्यविन्यास रूप से ठीक है, आप थोड़ी देर के लिए संदर्भ को भूल सकते हैं और 'आइटम' दस्तावेज़ के अंदर एम्बेडेड सरणी के साथ अपनी क्वेरी को आज़मा सकते हैं।
आफरीन शेख

दस्तावेज़ के साथ मेरी मूल पोस्ट को संपादित किया। मैं सफलता के साथ आइटम के अंदर एक एम्बेडेड सरणी के रूप में मॉडल के साथ इसका परीक्षण करने में सक्षम था, लेकिन दुर्भाग्य से मुझे इसकी आवश्यकता एक डीबीआरएफ के रूप में है क्योंकि आइटमटैग को अक्सर अपडेट किया जाता है। मदद के लिए एक बार फिर से धन्यवाद।
jschr

15

अपडेट: कृपया टिप्पणियों पर एक नज़र डालें - यह उत्तर प्रश्न से सही ढंग से मेल नहीं खाता है, लेकिन हो सकता है कि यह उपयोगकर्ताओं के अन्य प्रश्नों के उत्तर देता है, जो सामने आए (मुझे लगता है कि upvotes के कारण) इसलिए मैं इस "उत्तर" को नहीं हटाऊंगा:

पहला: मुझे पता है कि यह प्रश्न वास्तव में पुराना है, लेकिन मैंने इस समस्या की खोज की और यह SO पोस्ट Google प्रविष्टि # 1 थी। इसलिए मैंने docs.filterसंस्करण को लागू किया (उत्तर को स्वीकार किया) लेकिन जैसा कि मैंने mongoose v4.6.0 डॉक्स में पढ़ा है, अब हम बस उपयोग कर सकते हैं:

Item.find({}).populate({
    path: 'tags',
    match: { tagName: { $in: ['funny', 'politics'] }}
}).exec((err, items) => {
  console.log(items.tags) 
  // contains only tags where tagName is 'funny' or 'politics'
})

आशा है कि यह भविष्य के खोज मशीन उपयोगकर्ताओं की मदद करता है।


3
लेकिन यह केवल आइटम्स को फ़िल्टर करेगा। टेग्स सरणी निश्चित रूप से? टैग की परवाह किए बिना आइटम लौटाए जाएंगे ...
OllyBarca

1
यह सही है, @OllyBarca। डॉक्स के अनुसार, मैच केवल जनसंख्या क्वेरी को प्रभावित करता है।
andreimarinescu

1
मुझे लगता है कि यह सवाल का जवाब नहीं देता है
Z.Alpha

1
@ फ़ेबियन जो एक त्रुटि नहीं है। केवल जनसंख्या क्वेरी (इस मामले में fans) फ़िल्टर हो जाती है। लौटाया गया वास्तविक दस्तावेज (जो कि एक संपत्ति के रूप Storyमें समाहित है fans) प्रभावित या फ़िल्टर नहीं किया गया है।
EnKrypt

2
इस प्रकार यह उत्तर सही नहीं है, टिप्पणियों में वर्णित कारणों के लिए। भविष्य में इसे देखने वाला कोई भी व्यक्ति सावधान हो जाए।
EnKrypt

3

हाल ही में खुद को एक ही समस्या होने के बाद, मैं निम्नलिखित समाधान के साथ आया हूँ:

सबसे पहले, सभी आइटमटैग ढूंढें जहां टैगनाम या तो 'मजाकिया' या 'राजनीति' है और आइटमटैग _ids की एक सरणी लौटाते हैं।

फिर, उन आइटमों को खोजें, जिनमें सभी आइटमटैग _ids टैग सरणी में हैं

ItemTag
  .find({ tagName : { $in : ['funny','politics'] } })
  .lean()
  .distinct('_id')
  .exec((err, itemTagIds) => {
     if (err) { console.error(err); }
     Item.find({ tag: { $all: itemTagIds} }, (err, items) => {
        console.log(items); // Items filtered by tagName
     });
  });

मैंने इसे कैसे कास्ट किया है टैग्स = इस का इंतजार करें। टाइगोडेल .find ({नाम: {$ in:}}}}) .listinct ('_ id'); इसे वापस करें ।adviceModel.find ({टैग: {$ all: tagsIds}});
ड्रैगोस लुपेई

1

@aaronheckmann के जवाब मेरे लिए काम किया, लेकिन मैं बदलने के लिए किया था return doc.tags.length;के लिए return doc.tags != null;क्योंकि वह फ़ील्ड शामिल अशक्त अगर यह पॉप्युलेट अंदर लिखा शर्तों के साथ मेल नहीं खाता। तो अंतिम कोड:

query....
.exec(function(err, docs){
   docs = docs.filter(function(doc){
     return doc.tags != null;
   })
   // do stuff with docs
});
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.