Alright, let's take some time now and talk about the
unwind aggregation operator. In a lot of situations we're going
to want to count or do some other sort of
operation based on the values in an array field. We
need to use array field values in some way. So,
with this data We might want to answer a question like
the following: In our collection, who included the most user
mentions in their tweets? Now the reason why this is
relevant to the unwind operator is because user
mentions are included in our tweets inside an array
field. Now in this data, if you remember,
user mentions are found within the entity's sub-document, in
particular, in the user mentions field. User mentions
is an array that contains documents that represent each
individual user mention. So, what I'm going to do
here is pull up some examples using this query.
Now, here I'm using an operator that we haven't seen
before. All this says is give me back documents where
the user mentions field of the entities sub-document are of
length three. So, I'll pretty print this. Then, if we scroll
up, we can see that this example here does in
fact have three user mentions in it. And, just so
you have the full picture, entities, is a top level
field here. It has a sub document as a value and
user mentions is one of the fields of that
entities sub document. User mentions is an array value
field. And, we can see that it holds documents
that are shaped liked this Now, what we're interested in
are these screen names here, because these are the
names of users that are mentioned in this particular tweet.
And for any tweet that mentions a user, you're
going to have an array with documents like this inside
of it, naming the users mentioned. Now, what we want
to find out is a count of all the user mentions
made by an individual Twitter user. So what we're going to
have to do is look through all of the tweets. There'll
be some grouping involved, of course, because we want to
group together tweets by the same user. But we also want
to count the number of user mentions. Unwind is a convenient
tool for doing that to answer this particular question. Let's take
a look. Okay, so here's our aggregation pipeline.
Our first stage uses the unwind operator and it's
being run against that user mentions field. Now
remember that what unwind does, is creates a copy
of the containing document for any array field.
It duplicates all fields except for the items in
the array. And it will create one copy for
each element in the array. And the only difference
between all of the copies will be that this field
Will take on each of the different values in the array,
in the documents that are produced. So let me, let
me make this a little bit more concrete. If we take
a look at this again, for this particular tweet, the
unwind stage will produce three documents as output for this one
tweet document here. All of the other fields that we
see here, all of these, And everything else here in this
tweet document will be exactly the same. The one difference will be
that the user mentions field will have a single document as its
value in each of those three copies of this tweet. In the
first copy, it will have this as its value In the second copy,
it will have this and finally the third copy, it
will have this. So, in the documents that get passed along
to the next stage, in this case a group stage,
the documents will have a different value for the user mentions
field. Now, it turns out that in our case. What
we really care about is this splitting effect. Not so much
with the value of user mentions is each time through.
Because, what we're interested in doing in the next stage is
essentially counting all of the documents that
pass through to this group stage with the
same screen name for the user who created
the tweet. Because, again, remember. The question we're
after here is, who included the most user mentions in their tweets? So by the
time we get to this stage unwind will
have produced an individual document for every user
mention in the collection. And group then will
aggregate them together based on the screen name
of the user who created the tweet, will
then simple produce a count field here as
part of our group operation. And again remember
that sum imply increments this counter each time
you see the document that's aggregated together with
the screen name or a document that has
the same screen name. Then we do our sort
and limit states. So one question I'll put to you
here is does this count the number of unique
user mentions? That is to say if a twitter user
mentions the same user more than once does this
count each one of those mentions or does it count
all mentions of the same user as one mentions? If
its not unique mentions that are not being counted here
question I'll leave you with is what type of
aggregation pipeline would we need to put together in order
to count unique mentions. Of users. Okay, so let's
run this. And because we limited this to one, we
get one document in our result array with a
count of 21 for user mentions for this user. Now
in case it's not clear to you by this
point, the advantage of the aggregation framework in MongoDB is
that all of this work is being performed
server side. That means that for this particular query
all that comes across the network to our
client is just that one result we just looked
at. The aggregation framework is powerful, not just
because of the functionality it provides, but because of
the speed with which it can execute these queries
because this functionality is fundamental to the server itself.
حسنًا، لنخصص بعضًا من الوقت للتحدث عن
عامل تشغيل تفكيك aggregation. في كثير من المواقف، سنقوم
بإحصاء العدد أو إجراء نوع آخر من العمليات
استنادًا إلى القيم الموجودة في حقل الصفيف. ونحتاج
إلى استخدام قيم حقل الصفيف بطريقة ما. فباستخدام
هذه البيانات، يمكننا الإجابة عن أحد الأسئلة
على غرار ما يلي: في المجموعة الماثلة لدينا، من الذي عمد إلى تضمين
معظم إشارات المستخدم في تغريداته؟ ويكمن السبب الذي يرجع إليه ارتباط ذلك
بعامل تشغيل التفكيك في تضمين إشارات
المستخدم في التغريدات الموجودة داخل حقل
صفيف. وفيما يتعلق بهذه البيانات، تذكروا أن
إشارات المستخدم موجودة داخل مستند entities الفرعي، وفي
حقل user mentions. وحقل إشارات المستخدم
عبارة عن صفيف يشتمل على مستندات تمثل كل
إشارة للمستخدم على حدة. لذلك، سأعمد هنا إلى
.التوقف عند بعض الأمثلة التي تستعين بهذا الاستعلام
أستخدم هنا عامل تشغيل لم نتعرف عليه
من قبل. وهو في مجمله يسترجع المستندات التي
يُقدر طول حقل user mentions فيها والموجود في مستند entities الفرعي بالقيمة
3. إذًا، سأعمد إلى كتابة هذا. وإذا مرّرنا
لأعلى، يمكننا ملاحظة أن هذا المثال هنا يشتمل بداخله في حقيقة الأمر على
ثلاث إشارات للمستخدم. وبذلك، تكتمل الصورة
لديك، حيث إن الحقل entities هو حقل المستوى العلوي
،هنا. إذ يشتمل على مستند فرعي ممثل في قيمة
وتُعد إشارات المستخدم
أحد حقول مستند entities الفرعي. وحقل إشارات المستخدم هو حقل
قيمة صفيف. ويمكننا ملاحظة أنه يشتمل على مستندات
تأخذ شكلاً مشابهًا لهذا، في حين أن ما يجذب اهتمامنا يتمثل في
هذه الأسماء المعروضة على الشاشة هنا، حيث تمثل
.أسماء مستخدمين مشار إليهم في هذه التغريدة تحديدًا
وفيما يتعلق بأي من التغريدات التي تشير إلى مستخدم، سيكون لديك
،صفيف مقترن بمستندات على غرار هذا المستند وموجود بداخله
وذلك من خلال أسماء المستخدمين المشار إليهم. سنعمد الآن إلى
اكتشاف عدد جميع إشارات المستخدم
التي تم إنشاؤها بواسطة مستخدم فردي لموقع Twitter. إذًا، سيتعين
،تفحص جميع التغريدات. وسيتضمن ذلك إنشاء بعض المجموعات
وذلك لأننا نريد
تجميع التغريدات التي أنشأها المستخدم نفسه. ولكننا نريد أيضًا
إحصاء عدد إشارات المستخدم. ويُعد التفكيك
أداة ملائمة لتنفيذ ذلك من أجل الإجابة على هذا السؤال تحديدًا. لنلقِ
.نظرة. حسنًا، يرد هنا مسار aggregation
يتم في أول مرحلة استخدام عامل تشغيل التفكيك
ويتم تشغيله مقارنةً بحقل user mentions. تذكروا
أن التفكيك يؤدي إلى إنشاء نسخة
.من المستند المتضمن تشتمل على أي حقل صفيف
حيث يكرر جميع الحقول باستثناء العناصر الموجودة في
الصفيف. وسينشئ نسخة واحدة
لكل عنصر في الصفيف. والفرق الوحيد
بين جميع النسخ سيكمن في أن هذا الحقل
،سيشتمل على كل من هذه القيم المختلفة في الصفيف
وذلك في المستندات التي يتم إنشاؤها. دعوني أبرز
هذا الأمر بشكل أوضح. إذا أعدنا النظر في
هذه التغريدة تحديدًا، فسنجد أن
مرحلة التفكيك ستؤدي إلى إنشاء ثلاثة مستندات كمخرجات لمستند
التغريدة الموضح هنا. إن جميع الحقول الأخرى التي تظهر
لدينا هنا وأي شيء آخر في
مستند التغريدة سيكون مماثلاً بشكل دقيق. وسيكون الفرق الوحيد
في أن حقل user mentions سيشتمل على مستند واحد متمثل في
،قيمته المضمنة في كل من هذه النسخ الثلاث لهذه التغريدة. في النسخة الأولى
،سيشتمل على هذه كقيمة له؛ وفي النسخة الثانية
سيشتمل على هذه القيمة، وفي النسخة الثالثة، سيشتمل على
هذه القيمة. ففي المستندات التي يتم تمريرها خلال
،المرحلة التالية، وهي في هذه الحالة ممثلة في مرحلة المجموعة
ستشتمل المستندات على قيمة مختلفة لحقل
إشارات المستخدم. ويتضح ذلك الآن في الحالة الماثلة لدينا. ما يعنينا
حقًا هو أثر التقسيم هنا. والذي لا يؤثر تأثيرًا كبيرًا
.باستخدام قيمة إشارات المستخدم في كل مرة
لأن ما يهمنا تنفيذه في المرحلة التالية هو
إحصاء عدد جميع المستندات التي يتم تمريرها
عبر مرحلة المجموعة هذه باستخدام
اسم المستخدم نفسه الذي أنشأ
التغريدة. وتذكروا مرة أخرى أن السبب يرجع إلى أن السؤال الذي نتطلع إلى الإجابة عنه
هنا هو من عمد إلى تضمين معظم إشارات المستخدم في تغريداته؟ وبحلول الوقت
،الذي نصل فيه إلى مرحلة التفكيك
سنكون قد أنشأنا مستندًا فرديًا لكل إشارة للمستخدم
في المجموعة. وستؤدي المجموعة
إلى تجميع الإشارات معًا استنادًا إلى اسم المستخدم
الذي أنشأ التغريدة، ثم تنشئ
حقل عدد هنا
كجزء من عملية التجميع. وأُذكر مرة أخرى
بأن قيمة المجموع تشير إلى زيادة هذا العداد كلما
ظهر لك المستند المجمع مع
اسم المستخدم أو أحد المستندات المشتملة على
اسم المستخدم نفسه. ثم نضطلع بعملية الفرز
وتحديد الحالات. إذًا، السؤال المطروح عليك
هنا هو هل يؤدي ذلك إلى إحصاء عدد إشارات المستخدم
الفريدة؟ أقصد بذلك أنه في حالة إشارة مستخدم التغريدة
إلى المستخدم نفسه أكثر من مرة، فهل يؤدي ذلك إلى
إحصاء كل إشارة من تلك الإشارات أم إحصاء
جميع إشارات المستخدم نفسه كإشارات واحدة؟ وإذا
،كانت الإشارات الفريدة هي التي يتم إحصاؤها هنا
فالسؤال الذي سأطرحه عليكم يتعلق بماهية نوع
مسار aggregation الذي سنحتاج إلى تجميعه من أجل
إحصاء عدد الإشارات الفريدة للمستخدمين. حسنًا، لنباشر
عملية التشغيل. ولأننا حددنا هذه القيمة بالعدد 1، فسنحصل على
مستند واحد في صفيف النتيجة المقترن بالعدد
21 الذي يمثل حقل إشارات المستخدم لهذا المستخدم. وفي حالة
عدم وضوح الأمر بخصوص هذه
النقطة، فإن الميزة من إطار عمل aggregation في MongoDB تكمن في تنفيذ
هذا العمل بأكمله
من جانب الخادم. يعني ذلك أن جميع
ما يتم التعبير عنه فيما يخص هذا الاستعلام بعينه عبر الشبكة ووصولاً إلى
البرنامج العميل لا يؤدي إلا إلى نتيجة واحدة ممثلة في
النتيجة التي ألقينا نظرة عليها للتو. إن إطار عمل aggregation فعال، ليس فقط
بسبب ما يقدمه من وظائف، بل بسبب ما يتمتع به من
،سرعة يمكن من خلالها إجراء هذه الاستعلامات
.حيث تُعد هذه الوظائف أساسية للخادم نفسه
Muito bem. Vamos conversar agora sobre o
operador de agregação unwind. Em várias situações, vamos
querer contar ou fazer algum outro tipo de
operação com base nos valores em um campo de array. Precisamos
usar valores de campo de array de alguma maneira. Então,
com estes dados, podemos querer responder a perguntas
como a seguinte: Em nossa coleção, quem incluiu a maior quantidade de
user_mentions em seus tweets? Agora, o motivo pelo qual isso é
relevante para o operador unwind é porque
user_mentions está incluído em nossos tweets dentro de um campo
de array. Nestes dados, se você se lembrar,
user_mentions são encontrados dentro do subdocumento entities,
especificamente, no campo user_mentions. User_mentions
é um array que contém documentos que representam
as menções de cada usuário individual. Então, o que farei aqui
será obter alguns exemplos usando esta consulta.
Agora, estou usando um operador que ainda não tínhamos
visto. O que ele diz é: retorne documentos em que
o campo user_mentions do subdocumento entities tenha comprimento
igual a 3. Então, imprimirei isso. Em seguida, se rolarmos
para cima, poderemos ver que este exemplo aqui
tem três user_mentions. E, para que você
possa ter uma ideia geral, entities é um campo de nível
superior aqui. Ele tem um subdocumento como um valor e
user_mentions é um dos campos desse
subdocumento entities. User_mentions é um campo de valor
de array. Podemos ver que ele possui documentos
com este formato. Mas estamos interessados nestes
screen_names aqui, pois eles são os nomes dos usuários
que são mencionados neste tweet específico.
E, para qualquer tweet que mencione um usuário,
você terá um array com documentos como este dentro
dele, nomeando os usuários mencionados. Agora, o que queremos
descobrir é uma contagem de todos os user_mentions
feitos por um usuário individual do Twitter. Para isso, o que teremos de
fazer será analisar todos os tweets. Haverá
algum agrupamento envolvido, é claro, pois queremos
agrupar os tweets por usuários. Mas também queremos
contar o número de user_mentions. Unwind é uma ferramenta
conveniente para fazer isso e responder a essa pergunta específica. Vamos
ver. Bem, aqui estão nossos canais de agregação.
Nosso primeiro estágio usa o operador unwind e ele
está sendo executado em relação ao campo user_mentions. Lembre-se
de que o que unwind faz é criar uma cópia
do documento contido para qualquer campo de array.
Ele duplica todos os campos, exceto para os itens no
array. E ele criará uma cópia para cada
elemento no array. A única diferença entre
todas as cópias será que este campo
assumirá cada um dos diferentes valores no array,
nos documentos que serão produzidos. Então, deixe-me
concretizar isso um pouco mais. Se analisarmos
isso novamente, para este tweet em particular, a
fase de desenrolamento produzirá três documentos como saída para este
documento de tweet aqui. Todos os outros campos que
vemos aqui, todos estes, e tudo o mais aqui neste
documento de tweet serão exatamente iguais. A única diferença será que o
campo user_mentions terá um único documento como seu
valor em cada uma das três cópias deste tweet. Na
primeira cópia, ele terá isto como seu valor. Na segunda cópia,
ele terá isto e, por fim, a terceira cópia
terá isto. Assim, nos documentos passados para
o próximo estágio, neste caso o estágio group,
os documentos terão um valor diferente para o campo
user_mentions. Agora, acontece que, no nosso caso, o que
realmente nos interessa é saber sobre esse efeito de divisão. E não muito
qual será o valor de user_mentions a cada vez.
Porque o que estamos interessados em fazer no próximo estágio é,
essencialmente, contar todos os documentos
passados para este estágio group com
o mesmo screen_name para o usuário que criou
o tweet. Porque, de novo, lembre-se: a questão que queremos
responder aqui é: quem incluiu a maior quantidade de user_mentions em seus tweets? Portanto, quando
chegarmos neste estágio, unwind terá
produzido um documento individual para cada
user_mention na coleção. E o agrupamento deles
irá reuni-los com base no screen_name
do usuário que criou o tweet; em seguida,
nós apenas produziremos um campo count aqui como
parte de nossa operação group. Lembre-se novamente de que
sum apenas incrementa este contador toda vez
que você vê o documento que está vinculado ao
screen_name ou um documento que tenha
o mesmo screen_name. Então, definimos nossos estados de
sort e limit. Uma pergunta que tenho para você aqui é:
isso contará o número de
user_mentions exclusivos? Ou seja, se um usuário do Twitter
mencionar o mesmo usuário mais de uma vez, será
contabilizada cada uma dessas menções ou
todas as menções de um mesmo usuário será contabilizada como uma única menção? Se
não forem menções exclusivas que estão sendo contadas aqui,
a pergunta que faço a você é: quais tipos de
canais de agregação precisamos reunir para
contar menções exclusivas de usuários? Certo. Então, vamos
executar isso. E como limitamos isso a 1, obtemos
um documento em nosso array result com
count igual a 21 para user_mentions deste usuário. No caso
disso ainda não estar claro para você até
este ponto, a vantagem do framework de agregação no MongoDB é
que todo esse trabalho está sendo feito
no lado do servidor. Isso significa que, para esta consulta específica,
tudo o que vem pela rede para nosso
cliente é apenas aquele resultado que acabamos de
analisar. O framework de agregação é poderoso, não apenas
devido à funcionalidade que fornece, mas por causa da
velocidade com que consegue executar essas consultas,
pois essa funcionalidade é fundamental para o próprio servidor.
我们现在来讨论一下展开聚合运算符
在大多数情况下
我们可能需要计算
或者 根据数组字段中的值进行某种计算
我们需要使用数组字段值
所以 对于这个数据 我们可能需要回答这个问题
在我们的这些数据中
哪个用户的推文含有最多的用户提及次数?
它之所以与展开运算符相关
是因为用户提及次数位于推文的数组字段中
在这个数据中 如果你还记得
用户提及次数是在实体子文件
的用户提及字段中
用户提及次数是含有文件的数组
这些文件代表每个用户的提及次数
所以 我要通过查询抽取一些示例
在这里 我使用了一个之前没出现过的运算符
这些代码的意思是
返回实体子文件中用户提及字段的长度为3的文件
我把它打出来 如果我们把页面向上拉
我们可以看到
这个例子中确实有三个用户提及次数
为了让你充分理解 实体其实位于这个字段的上方
它将子文件作为值
而用户提及是这个实体子文件的一个字段
用户提及是一个数组值字段
我们可以看到
它含有形式类似于这个的文件
我们感兴趣的是这里的这些网名
因为 这条推特中提到了这些用户名
每出现提及一个用户的推文
你就会有一个含有这种文件的数组
它会说明所提及的用户
我们要找出的是
某一个 Twitter 用户提及的所有用户数量
我们需要查看所有的推文
这里当然还会涉及到分组
因为我们需要将同一用户的推特分为一组
但我们还想计算用户提及的次数
针对这个问题 展开运算符是一个非常方便的工具
这就是我们的聚合管道
我们的第一个阶段利用展开运算符
它是针对用户提及字段运行的
记住 展开的作用是
复制每个含有数组字段的文件
它会复制所有的字段
只有数组中的数据项除外
它会为数组中的每个元素创建一个副本
而所有副本的唯一区别就是
这个字段会在生成的文件中
载入数组中的每个值
我用具体的例子来讲解一下
我们再来看一下这条推文
针对这条推文的文件 展开阶段会生成三个输出文件
我们在这里看到的所有其它字段
以及这个推文文件中的其它数据都不变
它唯一的区别就是
在这条推文的三个副本中
用户提及字段的值都是一个单独的文件
在第一个副本中 它的值是这个
在第二个副本中 它的值是这个
而在第三个副本中 它的值是这个
在传递给下一阶段的文件中 也就是这里的分组阶段
这些文件的用户提及字段会有不同的值
在这个例子中
我们关注的是拆分的效果
而不是每次用户提及次数的具体值
因为 我们在下一个阶段要做的是
计算传递给下一阶段的所有文件数量
在这些文件中
创建这个推文的用户都拥有相同的网名
因为 我们要记住
这里的问题是 哪个用户推文中含有最多的用户提及次数有?
所以 在我们进入这个阶段时
展开阶段已经针对数据中的
每个用户提及次数生成了单独的文件
然后 分组阶段会根据创建该推文的用户网名
对这些文件进行聚合
然后 作为分组运算的一部分
它会在这里生成一个数量字段
不要忘了 每当出现经过聚合的文件拥有同样的网名
或拥有同样网名的文件
总数都会加上1
然后 我们进行排序和限制的运算
我要问你的一个问题是
这个做法计算的是特殊的用户提及次数吗?
也就是说 如果一位推特用户
多次提及同一个用户
它会计算所有的提及次数
还是把提到同一用户的提及次数算作一次?
如果这里计算的不是特殊的提及次数
那么 我要问你
如果要计算特殊的提及次数
我们需要构建什么样的聚合管道?
我们现在运算这个代码 由于我们限制了数量为1
所以 我们在结果数组中只得到了一个文件
这个用户的用户提及次数是21次
如果你仍然不太清楚
MongoDB 中聚合框架的优点是
所有这些工作都是在服务器端完成的
这意味着 就这次查询而言
我们的客户通过网络接收到的结果
只是我们刚才看到的那一条结果
聚合框架的作用十分强大
这不仅仅是源于它提供多项功能
还因为它执行这些查询的速度很快
这个功能对于服务器来说至关重要