Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
538 views
in Technique[技术] by (71.8m points)

node.js - MongoDB aggregation limit matches to 1 of each

I'm trying to use MongoDB aggregation get values that are in the idArray but doesn't exist as a doc:

 idArray = ["a", "b", "c"]

docs

     {node: "a", value: "3"}
     {node: "c", value: "3"}
     {node: "a", value: "1"}
     {node: "a", value: "4"}

   db.docs.aggregate([
      {$match:
        node: 
          $in: idArray}
      {$group: {"_id":null , "matches":{$addToSet:"$node"}} } 
      {$project:
        node_not_found: { $setDifference: [ INPUT_ARRAY, "$matches" ] }
        _id: 0}
    ]).each (err, node) ->

This should produce:

{ "node_not_found" : [ "b" ] }

My issue is that this is quite slow as it matches a multiple times and tries to push it all into the array. How do I limit the match to have only 1 of a so that duplicate work isn't done?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

How do I limit the match to have only 1

I don't think there is better way to limit document in match stage using $in query.

My issue is that this is quite slow as it matches

You need to avoid such array operations from your query,

  • remove last $project stage and do that operation in your client side,
  • create single field index on node field, it will be more effective for performance,
  • i am suggesting below query, i have not tested it but you can try may be it will help,

Suggestion 1:

  { $match: { node: { $in: ["a", "b", "c"] } } },
  { $group: { "_id": "$node" } }

Playground

Result:

[{ "_id": "c" }, { "_id": "a" }]

Suggestion 2:

  { $match: { node: { $in: ["a", "b", "c"] } } },
  { $group: { "_id": null, "matches": { $addToSet: "$node" } } }

Playground

Result:

[{ "_id": null, "matches": ["c", "a"] }]

Other stuff you can do in your client side code.

You can check state of your query using explain(), see the examples and you can try in your query like db.docs.explain().aggregate(..) it will provide each statistics of your query stages.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...