<!-- 
RSS generated by JIRA (9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66) at Thu Feb 08 08:36:40 UTC 2024

It is possible to restrict the fields that are returned in this document by specifying the 'field' parameter in your request.
For example, to request only the issue key and summary append 'field=key&field=summary' to the URL of your request.
-->
<rss version="0.92" >
<channel>
    <title>MongoDB Jira</title>
    <link>https://jira.mongodb.org</link>
    <description>This file is an XML representation of an issue</description>
    <language>en-us</language>    <build-info>
        <version>9.7.1</version>
        <build-number>970001</build-number>
        <build-date>13-04-2023</build-date>
    </build-info>


<item>
            <title>[GODRIVER-1565] Consolidate IndexModel spec generation helpers and add docs to require order-preserving types</title>
                <link>https://jira.mongodb.org/browse/GODRIVER-1565</link>
                <project id="14289" key="GODRIVER">Go Driver</project>
                    <description>&lt;p&gt;EDIT: We&apos;ve had a number of users try to use maps for the &lt;tt&gt;IndexModel.Keys&lt;/tt&gt; value. This is incorrect because index key specs are ordered, but Go maps do not guarantee that items will be returned in insertion order when reading. We should improve the docs for the &lt;tt&gt;Keys&lt;/tt&gt; field to mention that an order-preserving type is required, similar to the docs we have for &lt;tt&gt;Database.RunCommand&lt;/tt&gt;.&lt;/p&gt;

&lt;p&gt;While we&apos;re here, we can also consolidate some of the logic in the index name generation code by first calling &lt;tt&gt;transformBsoncoreDocument&lt;/tt&gt; to create the keys spec and passing that to &lt;tt&gt;getOrGenerateIndexName&lt;/tt&gt; to loop over it. This will likely be a small perf improvement, but it&apos;ll still be incorrect to use an unordered type for &lt;tt&gt;Keys&lt;/tt&gt;.&lt;/p&gt;

&lt;p&gt;&#160;&lt;/p&gt;

&lt;p&gt;ORIGINAL DESCRIPTION:&lt;/p&gt;

&lt;p&gt;If you want to create a compound index you should fill the following struct:&lt;/p&gt;

&lt;p&gt;&#160;&lt;/p&gt;
&lt;p/&gt;
&lt;div id=&quot;syntaxplugin&quot; class=&quot;syntaxplugin&quot; style=&quot;border: 1px dashed #bbb; border-radius: 5px !important; overflow: auto; max-height: 30em;&quot;&gt;
&lt;table cellspacing=&quot;0&quot; cellpadding=&quot;0&quot; border=&quot;0&quot; width=&quot;100%&quot; style=&quot;font-size: 1em; line-height: 1.4em !important; font-weight: normal; font-style: normal; color: black;&quot;&gt;
		&lt;tbody &gt;
				&lt;tr id=&quot;syntaxplugin_code_and_gutter&quot;&gt;
						&lt;td  style=&quot; line-height: 1.4em !important; padding: 0em; vertical-align: top;&quot;&gt;
					&lt;pre style=&quot;font-size: 1em; margin: 0 10px;  margin-top: 10px;   width: auto; padding: 0;&quot;&gt;&lt;span style=&quot;color: black; font-family: &apos;Consolas&apos;, &apos;Bitstream Vera Sans Mono&apos;, &apos;Courier New&apos;, Courier, monospace !important;&quot;&gt;// IndexModel represents a new index to be created.&lt;/span&gt;&lt;/pre&gt;
			&lt;/td&gt;
		&lt;/tr&gt;
				&lt;tr id=&quot;syntaxplugin_code_and_gutter&quot;&gt;
						&lt;td  style=&quot; line-height: 1.4em !important; padding: 0em; vertical-align: top;&quot;&gt;
					&lt;pre style=&quot;font-size: 1em; margin: 0 10px;   width: auto; padding: 0;&quot;&gt;&lt;span style=&quot;color: black; font-family: &apos;Consolas&apos;, &apos;Bitstream Vera Sans Mono&apos;, &apos;Courier New&apos;, Courier, monospace !important;&quot;&gt;type IndexModel struct {&lt;/span&gt;&lt;/pre&gt;
			&lt;/td&gt;
		&lt;/tr&gt;
				&lt;tr id=&quot;syntaxplugin_code_and_gutter&quot;&gt;
						&lt;td  style=&quot; line-height: 1.4em !important; padding: 0em; vertical-align: top;&quot;&gt;
					&lt;pre style=&quot;font-size: 1em; margin: 0 10px;   width: auto; padding: 0;&quot;&gt;&lt;span style=&quot;color: black; font-family: &apos;Consolas&apos;, &apos;Bitstream Vera Sans Mono&apos;, &apos;Courier New&apos;, Courier, monospace !important;&quot;&gt;	// A document describing which keys should be used for the index. It cannot be nil. See&lt;/span&gt;&lt;/pre&gt;
			&lt;/td&gt;
		&lt;/tr&gt;
				&lt;tr id=&quot;syntaxplugin_code_and_gutter&quot;&gt;
						&lt;td  style=&quot; line-height: 1.4em !important; padding: 0em; vertical-align: top;&quot;&gt;
					&lt;pre style=&quot;font-size: 1em; margin: 0 10px;   width: auto; padding: 0;&quot;&gt;&lt;span style=&quot;color: black; font-family: &apos;Consolas&apos;, &apos;Bitstream Vera Sans Mono&apos;, &apos;Courier New&apos;, Courier, monospace !important;&quot;&gt;	// https://docs.mongodb.com/manual/indexes/#indexes for examples of valid documents.&lt;/span&gt;&lt;/pre&gt;
			&lt;/td&gt;
		&lt;/tr&gt;
				&lt;tr id=&quot;syntaxplugin_code_and_gutter&quot;&gt;
						&lt;td  style=&quot; line-height: 1.4em !important; padding: 0em; vertical-align: top;&quot;&gt;
					&lt;pre style=&quot;font-size: 1em; margin: 0 10px;   width: auto; padding: 0;&quot;&gt;&lt;span style=&quot;color: black; font-family: &apos;Consolas&apos;, &apos;Bitstream Vera Sans Mono&apos;, &apos;Courier New&apos;, Courier, monospace !important;&quot;&gt;	Keys interface{}&lt;/span&gt;&lt;/pre&gt;
			&lt;/td&gt;
		&lt;/tr&gt;
				&lt;tr id=&quot;syntaxplugin_code_and_gutter&quot;&gt;
						&lt;td  style=&quot; line-height: 1.4em !important; padding: 0em; vertical-align: top;&quot;&gt;
					&lt;pre style=&quot;font-size: 1em; margin: 0 10px;   width: auto; padding: 0;&quot;&gt;&amp;nbsp;&lt;/pre&gt;
			&lt;/td&gt;
		&lt;/tr&gt;
				&lt;tr id=&quot;syntaxplugin_code_and_gutter&quot;&gt;
						&lt;td  style=&quot; line-height: 1.4em !important; padding: 0em; vertical-align: top;&quot;&gt;
					&lt;pre style=&quot;font-size: 1em; margin: 0 10px;   width: auto; padding: 0;&quot;&gt;&lt;span style=&quot;color: black; font-family: &apos;Consolas&apos;, &apos;Bitstream Vera Sans Mono&apos;, &apos;Courier New&apos;, Courier, monospace !important;&quot;&gt;	// The options to use to create the index.&lt;/span&gt;&lt;/pre&gt;
			&lt;/td&gt;
		&lt;/tr&gt;
				&lt;tr id=&quot;syntaxplugin_code_and_gutter&quot;&gt;
						&lt;td  style=&quot; line-height: 1.4em !important; padding: 0em; vertical-align: top;&quot;&gt;
					&lt;pre style=&quot;font-size: 1em; margin: 0 10px;   width: auto; padding: 0;&quot;&gt;&lt;span style=&quot;color: black; font-family: &apos;Consolas&apos;, &apos;Bitstream Vera Sans Mono&apos;, &apos;Courier New&apos;, Courier, monospace !important;&quot;&gt;	Options *options.IndexOptions&lt;/span&gt;&lt;/pre&gt;
			&lt;/td&gt;
		&lt;/tr&gt;
				&lt;tr id=&quot;syntaxplugin_code_and_gutter&quot;&gt;
						&lt;td  style=&quot; line-height: 1.4em !important; padding: 0em; vertical-align: top;&quot;&gt;
					&lt;pre style=&quot;font-size: 1em; margin: 0 10px;   margin-bottom: 10px;  width: auto; padding: 0;&quot;&gt;&lt;span style=&quot;color: black; font-family: &apos;Consolas&apos;, &apos;Bitstream Vera Sans Mono&apos;, &apos;Courier New&apos;, Courier, monospace !important;&quot;&gt;}&lt;/span&gt;&lt;/pre&gt;
			&lt;/td&gt;
		&lt;/tr&gt;
			&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p/&gt;
&lt;p&gt;Here the &quot;keys&quot; should be of type map. Let&apos;s assume we want to create the following compound index (without any options):&lt;/p&gt;
&lt;p/&gt;
&lt;div id=&quot;syntaxplugin&quot; class=&quot;syntaxplugin&quot; style=&quot;border: 1px dashed #bbb; border-radius: 5px !important; overflow: auto; max-height: 30em;&quot;&gt;
&lt;table cellspacing=&quot;0&quot; cellpadding=&quot;0&quot; border=&quot;0&quot; width=&quot;100%&quot; style=&quot;font-size: 1em; line-height: 1.4em !important; font-weight: normal; font-style: normal; color: black;&quot;&gt;
		&lt;tbody &gt;
				&lt;tr id=&quot;syntaxplugin_code_and_gutter&quot;&gt;
						&lt;td  style=&quot; line-height: 1.4em !important; padding: 0em; vertical-align: top;&quot;&gt;
					&lt;pre style=&quot;font-size: 1em; margin: 0 10px;  margin-top: 10px;   margin-bottom: 10px;  width: auto; padding: 0;&quot;&gt;&lt;span style=&quot;color: black; font-family: &apos;Consolas&apos;, &apos;Bitstream Vera Sans Mono&apos;, &apos;Courier New&apos;, Courier, monospace !important;&quot;&gt;{ &quot;item&quot;: 1, &quot;stock&quot;: -1 }&lt;/span&gt;&lt;/pre&gt;
			&lt;/td&gt;
		&lt;/tr&gt;
			&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p/&gt;
&lt;p&gt;&#160;&lt;/p&gt;

&lt;p&gt;The code could create all of the following indexes:&lt;/p&gt;

&lt;p&gt;1. index { &quot;item&quot;: 1, &quot;stock&quot;: -1 } with name item_1_stock_-1&lt;/p&gt;

&lt;p&gt;2. index { &quot;item&quot;: 1, &quot;stock&quot;: -1 } with name stock_-1_item_1&lt;/p&gt;

&lt;p&gt;3. index { &quot;stock&quot;: -1, &quot;item&quot;: 1 } with name item_1_stock_-1&lt;/p&gt;

&lt;p&gt;4. index { &quot;stock&quot;: -1, &quot;item&quot;: 1 } with name stock_-1_item_1&lt;/p&gt;

&lt;p&gt;&#160;&lt;/p&gt;

&lt;p&gt;&lt;b&gt;&lt;ins&gt;Explanation:&lt;/ins&gt;&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;First of all, it&apos;s important to understand why do we have this bug. in Go when you want to go over all the keys in map you use &apos;range&apos; clause in a for statement. The problem is that according to the &lt;a href=&quot;https://golang.org/ref/spec#For_statements&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;spec&lt;/a&gt;: &quot;The iteration order over maps is not specified and is not guaranteed to be the same from one iteration to the next.&quot;&lt;/p&gt;

&lt;p&gt;So if we insert a map to this &lt;b&gt;IndexModel&lt;/b&gt; struct the order is not guaranteed ! and as we know it&apos;s important in the case of compound index.&lt;/p&gt;

&lt;p&gt;&#160;&lt;/p&gt;

&lt;p&gt;Ok, but why do we have 4 options in the example above and not two?&lt;/p&gt;

&lt;p&gt;&#160;&lt;/p&gt;

&lt;p&gt;The reason is that if you don&apos;t specify a name in the &apos;Index Option&apos; it will generate one for you. The function that generates the name and the function that generates the keys are two different functions! they both go over the same map but do different things.&lt;/p&gt;

&lt;p&gt;And this is the two functions that I&apos;m referring to:&lt;/p&gt;

&lt;p&gt;&#160;&lt;/p&gt;

&lt;p&gt;&lt;font color=&quot;#000080&quot;&gt;func &lt;/font&gt;getOrGenerateIndexName(registry *bsoncodec.Registry, model IndexModel) (string, error)&lt;/p&gt;

&lt;p&gt;&lt;font color=&quot;#000080&quot;&gt;func &lt;/font&gt;transformBsoncoreDocument(registry *bsoncodec.Registry, val &lt;font color=&quot;#000080&quot;&gt;interface&lt;/font&gt;{}) (bsoncore.Document, error)&lt;/p&gt;

&lt;p&gt;&#160;&lt;/p&gt;

&lt;p&gt;&#160;&lt;/p&gt;

&lt;p&gt;&#160;&lt;/p&gt;</description>
                <environment></environment>
        <key id="1309060">GODRIVER-1565</key>
            <summary>Consolidate IndexModel spec generation helpers and add docs to require order-preserving types</summary>
                <type id="4" iconUrl="https://jira.mongodb.org/secure/viewavatar?size=xsmall&amp;avatarId=14710&amp;avatarType=issuetype">Improvement</type>
                                            <priority id="3" iconUrl="https://jira.mongodb.org/images/icons/priorities/major.svg">Major - P3</priority>
                        <status id="6" iconUrl="https://jira.mongodb.org/images/icons/statuses/closed.png" description="The issue is considered finished, the resolution is correct. Issues which are closed can be reopened.">Closed</status>
                    <statusCategory id="3" key="done" colorName="success"/>
                                    <resolution id="13201">Fixed</resolution>
                                        <assignee username="divjot.arora@mongodb.com">Divjot Arora</assignee>
                                    <reporter username="tamirav@checkpoint.com">Tamir Aviv</reporter>
                        <labels>
                    </labels>
                <created>Thu, 9 Apr 2020 01:33:33 +0000</created>
                <updated>Sat, 28 Oct 2023 11:38:14 +0000</updated>
                            <resolved>Fri, 8 May 2020 17:42:49 +0000</resolved>
                                    <version>1.3.2</version>
                                    <fixVersion>1.4.0</fixVersion>
                                    <component>Core API</component>
                                        <votes>0</votes>
                                    <watches>2</watches>
                                                                                                                <comments>
                            <comment id="3076243" author="xgen-internal-githook" created="Fri, 8 May 2020 17:42:31 +0000"  >&lt;p&gt;Author:&lt;/p&gt;
{&apos;name&apos;: &apos;Divjot Arora&apos;, &apos;email&apos;: &apos;divjot.arora@10gen.com&apos;, &apos;username&apos;: &apos;divjotarora&apos;}
&lt;p&gt;Message: &lt;a href=&quot;https://jira.mongodb.org/browse/GODRIVER-1565&quot; title=&quot;Consolidate IndexModel spec generation helpers and add docs to require order-preserving types&quot; class=&quot;issue-link&quot; data-issue-key=&quot;GODRIVER-1565&quot;&gt;&lt;del&gt;GODRIVER-1565&lt;/del&gt;&lt;/a&gt; Consolidate IndexView helpers and improve docs (#401)&lt;br/&gt;
Branch: master&lt;br/&gt;
&lt;a href=&quot;https://github.com/mongodb/mongo-go-driver/commit/067f7a8a2268a6714b94fab39c999dc7c95e27b6&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;https://github.com/mongodb/mongo-go-driver/commit/067f7a8a2268a6714b94fab39c999dc7c95e27b6&lt;/a&gt;&lt;/p&gt;</comment>
                            <comment id="3071939" author="divjot.arora" created="Wed, 6 May 2020 15:24:52 +0000"  >&lt;p&gt;&lt;a href=&quot;https://github.com/mongodb/mongo-go-driver/pull/401&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;https://github.com/mongodb/mongo-go-driver/pull/401&lt;/a&gt;&lt;/p&gt;</comment>
                            <comment id="3033368" author="divjot.arora" created="Thu, 9 Apr 2020 14:44:05 +0000"  >&lt;p&gt;&lt;a href=&quot;https://jira.mongodb.org/secure/ViewProfile.jspa?name=tamirav%40checkpoint.com&quot; class=&quot;user-hover&quot; rel=&quot;tamirav@checkpoint.com&quot;&gt;tamirav@checkpoint.com&lt;/a&gt; I&apos;ve changed the ticket title and description to match the work involved. We do have an existing example for creating indices at&#160;&lt;a href=&quot;https://pkg.go.dev/go.mongodb.org/mongo-driver/mongo?tab=doc#example-IndexView.CreateMany&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;https://pkg.go.dev/go.mongodb.org/mongo-driver/mongo?tab=doc#example-IndexView.CreateMany&lt;/a&gt;&#160;. Hopefully that&apos;s helpful for your use case.&lt;/p&gt;</comment>
                            <comment id="3032581" author="tamirav@checkpoint.com" created="Thu, 9 Apr 2020 11:07:50 +0000"  >&lt;p&gt;Hi &lt;a href=&quot;https://jira.mongodb.org/secure/ViewProfile.jspa?name=divjot.arora&quot; class=&quot;user-hover&quot; rel=&quot;divjot.arora&quot;&gt;divjot.arora&lt;/a&gt;,&lt;/p&gt;

&lt;p&gt;After reading about bson.D I agree, we should repurpose this ticket to improve the documentation of the &apos;Keys&apos; field to contains only order type (and give the bson.D as an example)&lt;/p&gt;

&lt;p&gt;About the two functions, it seems that if you use bson.D the order will be the same for each iteration in both functions, so we will get the same request each time. but I agree that it will be nicer to pass the transformed keys to &lt;tt&gt;getOrGenerateIndexName to avoid double transformation (the function getOrGenerateIndexName&lt;/tt&gt;&lt;tt&gt;also transformed the keys the same way transformBsoncoreDocument&lt;/tt&gt; does)&lt;/p&gt;

&lt;p&gt;&#160;&lt;/p&gt;

&lt;p&gt;Thanks for your fast reply!&lt;/p&gt;

&lt;p&gt;Tamir.&lt;/p&gt;</comment>
                            <comment id="3032290" author="divjot.arora" created="Thu, 9 Apr 2020 01:52:18 +0000"  >&lt;p&gt;Hi &lt;a href=&quot;https://jira.mongodb.org/secure/ViewProfile.jspa?name=tamirav%40checkpoint.com&quot; class=&quot;user-hover&quot; rel=&quot;tamirav@checkpoint.com&quot;&gt;tamirav@checkpoint.com&lt;/a&gt;,&lt;/p&gt;

&lt;p&gt;This is an issue we&apos;ve seen other users run into as well. This isn&apos;t really a bug in the driver because, as you mention, maps in Go do not guarantee that keys will be returned in insertion order when the map is iterated. Even if there were not two functions that iterated the map, this would still be an issue because a you could specify the map {x: 1, y: 1} but the created index could be {y: 1, x: 1}, which is incorrect.&lt;/p&gt;

&lt;p&gt;The resolution here is to use an ordered type like bson.D. Given that others have run into this as well, I think we should repurpose this ticket as an improvement to do two things:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;Consolidate some of the code in the two functions you mentioned. We can probably call &lt;tt&gt;transformBsoncoreDocument&lt;/tt&gt; first and then pass the transformed document to &lt;tt&gt;getOrGenerateIndexName&lt;/tt&gt;.&lt;/li&gt;
	&lt;li&gt;Add documentation to indicate that the &lt;tt&gt;Keys&lt;/tt&gt; field should be an order-preserving type, similar to the documentation we have for &lt;tt&gt;Database.RunCommand&lt;/tt&gt;.&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;Thoughts?&lt;/p&gt;</comment>
                    </comments>
                    <attachments>
                    </attachments>
                <subtasks>
                    </subtasks>
                <customfields>
                                                                                                                                                                                                                                                                                                                                                                    <customfield id="customfield_15850" key="com.atlassian.jira.plugins.jira-development-integration-plugin:devsummary">
                        <customfieldname>Development</customfieldname>
                        <customfieldvalues>
                            
                        </customfieldvalues>
                    </customfield>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    <customfield id="customfield_12550" key="com.pyxis.greenhopper.jira:gh-lexo-rank">
                        <customfieldname>Rank</customfieldname>
                        <customfieldvalues>
                            <customfieldvalue>2|hx1ti7:</customfieldvalue>

                        </customfieldvalues>
                    </customfield>
                                                                <customfield id="customfield_10558" key="com.pyxis.greenhopper.jira:gh-global-rank">
                        <customfieldname>Rank (Obsolete)</customfieldname>
                        <customfieldvalues>
                            <customfieldvalue>9223372036854775807</customfieldvalue>
                        </customfieldvalues>
                    </customfield>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            </customfields>
    </item>
</channel>
</rss>