2016-05-24 6 views
2

Ich habe eine Sammlung Produkt und jedes Dokument sieht in etwa wie folgt aus:Wie kann ich ein verschachteltes Dokument abfragen und Attribute von ihm zurückgeben?

"_id" : ObjectId("574393c59afcfdd3763d91b1"), 
    "name" : "dummy product name", 
    "price" : 200, 

    "category" : ObjectId("574393c59afcfdd3763d91ad"), 
    "images" : [ ], 
    "ratings" : [ 
      2 
    ], 
    "reviews" : [ ], 
    "purchase_count" : 0, 
    "tags" : [ 
      ObjectId("574393c59afcfdd3763d91a9"), 
      ObjectId("574393c59afcfdd3763d91ab") 
    ] 

Wo Kategorie und Tags Verweise auf ihre jeweiligen Sammlungen sind und sie haben jeweils ein Namensattribut. Hier sind alle drei Schemata:

var ProductSchema = new mongoose.Schema({ 
    name : {type: String, required: true}, 
    price : { type: Number,required: true }, 
    tags : [{ type: Schema.Types.ObjectId, ref: 'Tag' }], 
    purchase_count : {type: Number, default: 0}, 
    reviews : [ReviewSchema], 
    ratings : [{type: Number, min: 0, max: 10}], 
    category : {type: Schema.Types.ObjectId, ref: 'ProductCategory'}, 
    images : [{type: String}] 
}); 

    var ProductCategorySchema = new mongoose.Schema({ 
    name : { type: String, required: true, unique: true, dropDups: true }}); 

    var TagSchema = new mongoose.Schema({ 
    name : { type: String, required: true, unique: true, dropDups: true, lowercase: true } 
}); 

Ich versuche, die Produktsammlung zur Abfrage und Rück Daten jedes Produkt wie folgt aus:

app.models.Product.find({}, function(err, products){ 
    if (err) throw err; 
    res.json(products); 
}).populate('category').populate('tags').exec(); 

Der einzige der Unterschied ist, dass ich den tatsächlichen Namen wollen von die Kategorie anstelle eines Dokuments, das die Sammlung mit ihrer ID darstellt. Ich möchte auch das gleiche für die Tags, ich möchte nur ein einfaches Array von Strings, die die Tag-Namen darstellen. Wie kann ich das in der Abfrage tun?

Ich versuchte implizit zu definieren, was ich auswählen wollte, indem Sie eine select() nach dem zweiten populate() und schreiben 'category.name tags.name (und dann alle anderen Attribute)' aber das hat nicht funktioniert.

Dies ist, was das Ergebnis der Abfrage wie folgt aussieht:

enter image description here

Antwort

0

Um bestimmtes Feld zu wählen Sie würde

app.models.Product.find({}, function(err, products){ 
    if (err) throw err; 
    res.json(products); 
}).populate('category', 'fieldname1 fieldname2').populate('tags', 'fieldname1 fieldname2').exec(); 

http://mongoosejs.com/docs/populate.html

Jedoch i in Ihrem Schema Definition nicht sehen irgendeine Bezugnahme auf irgendetwas.

Auch wenn Sie irgendeine Art von Beziehung haben/brauchen (was Sie scheinen zu brauchen), benutzen Sie nicht mongo.

Eigentlich nicht Mongo jemals verwenden, wenn Sie unbedingt müssen - versuchen, einen Weg von Mongo zu bleiben.

Update

So ähnlich.

var res = app.models.Product.find({}, function(err, products){ 
    if (err) throw err; 
    res.json(products); 
}).populate('category', 'fieldname1 fieldname2').populate('tags', 'fieldname1 fieldname2').exec(); 

res.category = categoty.fieldname; 
res.tags = res.tags.map(function(tag){ 

    return tag.fieldname 
}) 

Eine weitere Option könnte sein - Getter hinzuzufügen - nicht sicher, ob dies, weil bevöl nach so ..

aber geschehen könnte funktionieren:

ProductSchema.virtual('categoryString').get(function() { 
    return this.category.fieldname 
}); 

ProductSchema.virtual('tagsArr').get(function() { 
    return this.tags.map(function(tag){ 
    if(tag && tag.name) { 
     return tag.fieldname; 
    } 
    return ''; 
    }); 
}); 
+0

Ich versuchte das auch. Sie gibt das Dokumentobjekt zwar zurück, behält jedoch nur die von Ihnen angegebenen Felder bei. – ninesalt

+0

Und Sie wollen es so etwas wie user.category = ['cat1', 'cat2']? –

+0

Die Kategorie ist nur eine einzelne Zeichenfolge, aber die Tags sollten so sein, ja. – ninesalt

0

Ich weiß nicht, warum Senden Sie die Antwort, bevor Sie die Abfrage füllen. Verwenden Sie das Paket lodash, um Ihre Produkte vor der Reaktion zu ändern.

var _ = require('lodash'); 

app.models.Product.find({}).populate('category tags').exec(function(err, products){  
    if (err) throw err; 
    var modified = _.map(products, function (product) { 
     product.tags = _.map(product.tags, function (tag) { return _.pick(tag, ['name']) }); 
     product.category = _.pick(product.category, ['name']); 
     return product; 
    });  
    res.json(modified); 
}); 
+0

Das Gleiche. Gibt immer noch Kategorie und Tags als Dokumente zurück. – ninesalt

+0

ja, _id archiviert immer vorhanden. aber Name der Tags und Kategorie sind auch vorhanden? – KibGzr

+0

Ja, aber sie sind in dem Objekt, so dass ich nicht weiß, wie man auf sie zugreift. – ninesalt

1

So habe ich es funktioniert. Der Dank geht an Neta Meta für die Idee, reines JS zu verwenden.

app.models.Product.find({}) 
.populate('category' , 'name') 
.populate('tags', 'name').populate('seller', 'name').exec(function(err, products){ 

    if (err) throw err; 

    products = products.map(function(a){ 

    var productToSend = {}; 
    productToSend.name = a.name; 
    productToSend.price = a.price; 
    productToSend.description = a.description; 

    if(a.seller != undefined){ 
     productToSend.seller = a.seller.name; 
    } 

    if(a.tags != undefined){ 
     productToSend.tags = a.tags.map(function(b){ 
     return b.name; 
     }); 
    } 
    productToSend.purchase_count = a.purchase_count; 
    productToSend.reviews = a.reviews; 
    productToSend.ratings = a.ratings; 

    if(a.category != undefined){ 
     productToSend.category = a.category.name; 
    } 

    productToSend.images = a.images; 

    return productToSend; 

    }) 
    res.json(products); 
}); 
Verwandte Themen