Вычтите элементы списка, используя другой список в Python

Есть два способа вычесть элементы из списка, используя другой список, в зависимости от того, есть ли в вашем списке повторяющиеся значения или нет.

Если в вашем списке есть повторяющиеся значения, вы можете использовать понимание списка с условным ifоператором

Если в вашем списке нет повторяющихся значений, вы можете преобразовать списки в наборы, вычесть элементы и преобразовать результат в список.

Этот учебник покажет вам, как использовать оба метода на практике.

1. Использование понимания списка и условного

Чтобы вычесть элементы из одного списка, используя другой список, вы можете использовать понимание списка и условный ifоператор.

Например, предположим, что вы хотите вычесть элементы из list_1использования list_2, как показано ниже:

list_1 = [1, 2, 3, 3, 5, 6, 7, 7, 9]
list_2 = [2, 3, 9]

# subtract elements from list_1 using list_2
result = [x for x in list_1 if x not in list_2]

print(result)

Выход:

[1, 5, 6, 7, 7]

Здесь успешно вычитаются элементы 2, 3 и 9 list_1.

Этот метод рекомендуется при наличии повторяющихся значений в исходном списке.

2. Использование разности наборов

Объект setв Python может вычитать элементы из набора только с помощью -оператора минус.

Если в вашем списке нет повторяющихся значений, вы можете преобразовать список следующим образом:

list_1 = [1, 2, 3, 3, 5, 6, 7, 7, 9]
list_2 = [2, 3, 9]

# subtract elements as set objects
result = set(list_1) - set(list_2)

# convert result back to list
result = list(result)

print(result)

Выход:

[1, 5, 6, 7]

Обратите внимание, что повторяющиеся значения удаляются при преобразовании списка в набор.

Это связано с тем, что набор не может содержать повторяющиеся значения в Python.

Заключение

В этом руководстве показано два самых простых способа вычитания элементов списка с помощью другого списка в Python.

Используйте понимание списка, когда у вас есть повторяющиеся значения, или используйте set()функцию для преобразования объекта и вычитания с помощью -оператора минус.

Я надеюсь, что это руководство поможет. До встречи на других уроках!

Оригинальный источник статьи: https://sebhastian.com/

#python #elements #another 

Вычтите элементы списка, используя другой список в Python
佐藤  桃子

佐藤 桃子

1684565775

在 Python 中使用另一个列表减去一个列表元素

有两种方法可以使用另一个列表从列表中减去元素,具体取决于您的列表是否具有重复值。

if如果您的列表有重复值,那么您可以使用带有条件语句的列表理解

如果您的列表没有重复值,您可以将列表转换为集合,减去元素,并将结果转换为列表。

本教程将向您展示如何在实践中使用这两种方法。

1.使用列表理解和条件

要使用另一个列表从一个列表中减去元素,您可以使用列表理解和条件if语句。

例如,假设您要从list_1using中减去元素list_2,如下所示:

list_1 = [1, 2, 3, 3, 5, 6, 7, 7, 9]
list_2 = [2, 3, 9]

# subtract elements from list_1 using list_2
result = [x for x in list_1 if x not in list_2]

print(result)

输出:

[1, 5, 6, 7, 7]

此处,元素2、3、9减法成功list_1

当您在原始列表中有重复值时,建议使用此方法。

2.使用集差

Python 中的对象set仅使用减号运算符就可以从集合中减去元素-

如果您的列表没有重复值,那么您可以将列表转换为如下设置:

list_1 = [1, 2, 3, 3, 5, 6, 7, 7, 9]
list_2 = [2, 3, 9]

# subtract elements as set objects
result = set(list_1) - set(list_2)

# convert result back to list
result = list(result)

print(result)

输出:

[1, 5, 6, 7]

请注意,将列表转换为集合时会删除重复值。

这是因为在 Python 中集合不能包含重复值。

结论

本教程向您展示了在 Python 中使用另一个列表减去一个列表元素的两种最简单的方法。

当您有重复值时使用列表理解,或使用函数set()转换对象并使用减号-运算符减去。

我希望本教程有所帮助。在其他教程中见!

原始文章来源:https: //sebhastian.com/

#python #elements #another 

在 Python 中使用另一个列表减去一个列表元素
Nat  Grady

Nat Grady

1684558155

Subtract A List Elements using another List in Python

There are two ways you can subtract elements from a list using another list, depending on whether your list has duplicate values or not.

If your list has duplicate values, then you can use a list comprehension with a conditional if statement

If your list has no duplicate values, you can transform the lists into sets, subtract the elements, and convert the result into a list.

This tutorial will show you how to use both methods in practice.

1. Using a list comprehension and a conditional

To subtract elements from one list using another list, you can use a list comprehension and a conditional if statement.

For example, suppose you want to subtract elements from list_1 using list_2 as shown below:

list_1 = [1, 2, 3, 3, 5, 6, 7, 7, 9]
list_2 = [2, 3, 9]

# subtract elements from list_1 using list_2
result = [x for x in list_1 if x not in list_2]

print(result)

Output:

[1, 5, 6, 7, 7]

Here, the elements 2, 3, and 9 are subtracted from list_1 successfully.

This method is recommended when you have duplicate values in the original list.

2. Using set difference

The set object in Python is able to subtract elements from a set by only using the minus - operator.

If your list has no duplicate values, then you can convert the list to set as follows:

list_1 = [1, 2, 3, 3, 5, 6, 7, 7, 9]
list_2 = [2, 3, 9]

# subtract elements as set objects
result = set(list_1) - set(list_2)

# convert result back to list
result = list(result)

print(result)

Output:

[1, 5, 6, 7]

Notice that duplicate values are removed when you convert a list to a set.

This is because a set can’t contain duplicate values in Python.

Conclusion

This tutorial has shown you two easiest ways to subtract a list elements using another list in Python.

Use a list comprehension when you have duplicate values, or use the set() function to convert the object and subtract using minus - operator.

I hope this tutorial helps. See you in other tutorials!

Original article source at: https://sebhastian.com/

#python #elements #another 

Subtract A List Elements using another List in Python
Gordon  Murray

Gordon Murray

1673450520

Migrate/Copy List From One Site Collection To Another

Follow the steps mentioned below to migrate/copy a list from one site collection to another. 

Export the list

  • Login to SharePoint and go to List Settings. 
  • Under the Permissions and Management section click on Save list as template. 

Export list to another site collection 

  • On the top-level site of the site collection containing the list that you want to copy, click - > Site Settings. 
  • In the Galleries section, click - > List templates. 
  • On the List Template Gallery page, select the check box next to the list template that you want to export. 
  • In the ribbon Click - >Download a Copy. 

Uploading the list to a new site collection. 

  • You should now have a .stp file. Now go to the site collection you want to copy the list too. 
  • Click Site Settings. 
  • In the Galleries section, click on List templates. 
  • Click on the Documents tab. 
  • Click on Upload Document.
  • Click on Choose File and navigate and choose the .stp file you downloaded. 
  • Click on Ok. 

Problem: "Save List as Template" is missing in SharePoint Online modern sites.

Root Cause

"Custom script" feature is disabled! 

Solution

Enable Custom Scripting at SharePoint Admin Center and Site Collection Levels. 

How to Enable Custom Script in SharePoint Online? 

To allow custom script in SharePoint Online, follow these steps: 

  • Sign in to Office 365 and go to the SharePoint Online Admin Center. 
  • Click on Settings from the left navigation >> Scroll down to "Custom Script" section 
  • Under Custom Script section, set "Allow users to run custom script on personal site" and "Allow users to run custom script on self-service created sites" options.? 

How To Migrate / Copy List From One Site Collection To Another?

Click on "OK" to save your changes. 

This enables custom script in SharePoint Online. However, this change may take up to 24 Hours to reflect.

How To Migrate / Copy List From One Site Collection To Another?

Original article source at: https://www.c-sharpcorner.com/

#sharepoint #another 

Migrate/Copy List From One Site Collection To Another
Nat  Grady

Nat Grady

1665474900

Monaco: Yet another Second Editor in RStudio

Monaco: the Monaco editor as a HTML widget

Yet another second editor in RStudio.

The Monaco editor is the code editor which powers 'VS Code'. It is particularly well developed for JavaScript. In addition to the built-in features of the Monaco editor, the widget allows to prettify multiple languages, to view the HTML rendering of Markdown code, and to view and resize SVG images.

With the help of htmltools::browsable, one can open two Monaco editors in the RStudio viewer pane:

The Monaco editor has many options. If you would like some of them to be available in the monaco package, please fill an issue.

As any HTML widget, the Monaco editor widget can be used in Shiny apps:

This app uses the sass package to compile some SCSS code to CSS code. It is one of the examples provided in the monaco package.

Related projects

  • shinyMonacoEditor: the Monaco editor in a sophisticated Shiny app. It is more developed than the monaco widget but using the Shiny app locks RStudio.
  • aceEditor: the Ace editor as a HTML widget.

Download Details:

Author: stla
Source Code: https://github.com/stla/monaco 
License: View license

#r #rstudio #another #second #editor 

Monaco: Yet another Second Editor in RStudio

Node-jumplist: Yet another Implement Of Skiplist in Nodejs

Skiplist

Yet another implement of skiplist in nodejs

Install

npm install jumplist

Examples

var JumpList = require('jumplist');
var list = new JumpList();
list.set('a', 5);
list.set('b', 6);
list.set('c', 8);
list.set('d', 9);
list.get('b');
>>> 6 
list.remove('a');
list.get('a');
>>> undefined

list.range('c', 'e', function(key, value) {
  console.info('=', key, value);
});
>> = c 8
>> = d 9

list.getAt(0);
>> {key: 'b', value: 6}

list.getAt(2);
>> {key: 'd', value: 9}

Download Details:

Author: Superisaac
Source Code: https://github.com/superisaac/node-jumplist 
License: Unlicense license

#javascript #node #another 

Node-jumplist: Yet another Implement Of Skiplist in Nodejs
Desmond  Gerber

Desmond Gerber

1653737280

KambojaJS: New Meteoris, A MVC and Modular Framework for Meteor

WHAT IS METEORIS?

Meteoris is a Realtime MVC + Modular Javascript Framework based on Meteor 1.2.0. This is the latest version of Meteoris out there. In this version, Meteoris still doesn't have a code generator. If you prefer using the old version of meteoris, please use this version https://github.com/radiegtya/meteoris-v1.

QUICKSTART

1. Install Meteor, Create New Project & Download Required Packages

#install meteor
curl https://install.meteor.com/ | sh

#create new meteor project
meteor create my-meteoris-app

#the main module
meteor add meteoris:core

#another important module
meteor add meteoris:theme-admin
meteor add meteoris:user
meteor add meteoris:role

#remove meteor unused package
meteor remove insecure
meteor remove autopublish

2. Create hooked Navbar and Sidebar inside your "root/client/hook" folder

We can easily hook navbar and sidebar to customize our own sidebar and navbar although we are using meteoris:admin-theme template. The content of each template is using navbar and sidebar Admin LTE style. Make sure you are using correct theme name "meteoris_themeAdmin_hookNavbar" for sidebar, and "meteoris_themeAdmin_hookSidebar" for navbar.

<template name="meteoris_themeAdmin_hookNavbar">
    <div class="navbar-custom-menu">
        <ul class="nav navbar-nav">
            {{#if currentUser}}
            <!-- User Account: style can be found in dropdown.less -->
            <li class="dropdown user user-menu">
                <a href="#" class="dropdown-toggle" data-toggle="dropdown">
                    <img src="/images/user.png" class="user-image" alt="User Image">
                    <span class="hidden-xs">{{currentUser.profile.name}}</span>
                </a>
                <ul class="dropdown-menu">
                    <!-- User image -->
                    <li class="user-header">
                        <img src="/images/user.png" class="img-circle" alt="User Image">
                        <p>
                            {{currentUser.profile.name}}
                        </p>
                    </li>
                    <!-- Menu Footer-->
                    <li class="user-footer">
                        <div class="pull-left">
                            <a href="#" class="btn btn-default btn-flat">Profile</a>
                        </div>
                        <div class="pull-right">
                            <a href="#" id="btnLogout" class="btn btn-default btn-flat">Logout</a>
                        </div>
                    </li>
                </ul>
            </li>
            {{else}}
            <li>
                <a href="/meteoris/user/login">Login</a>
            </li>
            {{/if}}
        </ul>
    </div>
</template>

"at root/client/hook/navbar.html"

var ctrl = new Meteoris.UserController();

Template.meteoris_themeAdmin_hookNavbar.events = {
    'click #btnLogout': function(){
        ctrl.logout();
    }
};

"at root/client/hook/navbar.js"

<template name="meteoris_themeAdmin_hookSidebar">
    <!-- Left side column. contains the logo and sidebar -->
    <aside class="main-sidebar">
        <!-- sidebar: style can be found in sidebar.less -->
        <section class="sidebar">
            {{#if currentUser}}
            <!-- Sidebar user panel -->
            <div class="user-panel">
                <div class="pull-left image">
                    <img src="/images/user.png" class="img-circle" alt="User Image">
                </div>
                <div class="pull-left info">
                    <p>{{currentUser.profile.name}}</p>
                    <a href="#"><i class="fa fa-circle text-success"></i> Online</a>
                </div>
            </div>
            {{/if}}
            <!--search form--> 
            <form action="#" method="get" class="sidebar-form">
                <div class="input-group">
                    <input type="text" name="q" class="form-control" placeholder="Search...">
                    <span class="input-group-btn">
                        <button type="submit" name="search" id="search-btn" class="btn btn-flat"><i class="fa fa-search"></i></button>
                    </span>
                </div>
            </form>
            <!--/.search form--> 
            <!-- sidebar menu: : style can be found in sidebar.less -->
            <ul class="sidebar-menu">
                <li class="header">MAIN NAVIGATION</li>
                <li><a href="/"><i class="fa fa-home"></i> Home</a></li>
                <!--Uncomment this if you want to hide this menu using the power of meteoris:role-->
                <!--{{#if meteoris_roleUserIsInGroup "admin"}}-->
                <li class="header">ADMIN AREA</li>                
                <li class="treeview">
                    <a href="#">
                        <i class="fa fa-gears"></i>
                        <i class="fa fa-angle-left pull-right"></i>
                        <span>Setting</span>                                
                    </a>
                    <ul class="treeview-menu">                        
                        <li><a href="/meteoris/theme-admin/setting"><i class="fa fa-laptop"></i> Theme Admin Setting</a></li>                        
                        <li><a href="/meteoris/user"><i class="fa fa-users"></i> Users Management</a></li>                        
                        <li><a href="/meteoris/user/settings"><i class="fa fa-user"></i> User Settings</a></li>                                         
                        <li><a href="/meteoris/role"><i class="fa fa-flag-o"></i> Role Management</a></li>                                                
                    </ul>
                </li>
                <!--{{/if}}-->
            </ul>
        </section>
        <!-- /.sidebar -->
    </aside>        
</template>

"at root/client/hook/sidebar.html"

3. Creating Home/Site Page

Meteoris use simple MVC or MVVM + Modular paradigm to structuring app. Please use this standard structure to achieve best result when using meteoris.

3.1. Folder Structure

root/
  meteorusernameorgroup:module/
	client/             # Client folder
	   views/           # Views for html/js files
	lib/                # Both Access folder
	   collections/     # Collections folder
	   controllers/     # Controllers Folder
	   router.js        # Router js file
	server/             # Server folder			   

3.2. Router Meteoris using Kadira Flow Router to linking between pages. Because we are using modular technique, assume that we are using my meteor account called "radiegtya" and using module name called "site". So we should make folder under root folder called "radiegtya:site". To use modular router, simply follow this step:

  • create router file on "root/radiegtya:site/lib/router.js", and type this code
/**
create group routes, so every router has prefix radiegtya
*/
var groupRoutes = FlowRouter.group({
    prefix: '/radiegtya',
    name: 'radiegtya',
});

/**
create the main router called site, and use BlazeLayout render "meteoris_themeAdminMain" from metoris:theme-admin package, and accessing template called "radiegtya_siteIndex"
*/
groupRoutes.route('/site', {
    action: function() {
        BlazeLayout.render('meteoris_themeAdminMain', {content: "radiegtya_siteIndex"});
    },   
});
  • We are not yet able to use this router, but once you have created the views, you can access this page by calling this route:
localhost:3000/radiegtya/site

3.3. Creating Controller for Site Controller actually just a method to be called inside your template js, and this will make your code more modular and readable.

  • Create controller file on "root/radiegtya:site/lib/controller/SiteController.js"
/*
create a namespace called Radiegtya.SiteController
*/
Namespace('Radiegtya.SiteController');

/**
Create controller which extends Meteoris Controller
*/
Radiegtya.SiteController = Meteoris.Controller.extend({
	constructor : function() {
            // set default counter at constructor
            Session.setDefault('counter', 0);
        },
        /* passing data to index helpers template */
	index: function() {			        
		//return some value, to be passed on index.js
		return {
		    counter: this.getCounter(),
			myName: "Ega Radiegtya",
			myHobby: "Drinking Coffee"
		};
	},
	getCounter: function(){
		return Session.get("counter");
	},
	setCounter: function(counter){
		Session.set('counter', this.getCounter() + 1);
	}
});

3.4. Creating Views Page for Site

  • create views index file on "root/radiegtya:site/client/views/index.html". Look at the template naming convention, it use "meteorusername_moduleAction" namespacing, so for this views we are gonna use "radiegtya_siteIndex". Which is "radiegtya" for meteor username, "site" for the module name, and "Index" in camel case after site as action name.
<template name="radiegtya_siteIndex">
	<div class="content">
		<div class="box">
			<div class="box-body">
				<button>Click Me</button>
				<p>
				You've pressed the button {{counter}} times.
				</p>
			</div>
		</div>
	</div>
</template>

because we are installing meteoris:theme-admin, you can use adminLTE styling and html inside your views html file. We are using meteor example to make You more familiar with the code.

  • Don't forget to add the js file for the index. Create this file on "root/radiegtya:site/client/views/index.js"
var ctrl = new Radiegtya.SiteController();

/**
In the template helper section we are using index() method to get object return value from controller. It's because index was the action and also the file name suffix. This structure will make You easier to get jobs done, when your team getting bigger and the code getting bigger.
*/
Template.radiegtya_siteIndex.helpers({
	myName: function () {
		return ctrl.index().myName;
	},
	myHobby: function () {
		return ctrl.index().myHobby;
	},	
    counter: function () {
      return ctrl.index().counter;
    }
  });

/**
in the template events, we don't need to use index() method to call any action. Because it just simply method calling through controller.
*/
Template.radiegtya_siteIndex.events({
    'click button': function () {
      //increment the counter when button is clicked
      ctrl.setCounter();      
    }
});

Now finally access this route to check your apps.

localhost:3000/radiegtya/site

enter image description here

Awesome! We are successfully creating our simple app in MVC and Modular way with very easy setup. Ofc with amazing template which is reusable. You can also use this code to create a meteor package easily.

3.5. Creating Collection You can use aldeed:collection2, aldeed:simple-schema, and dburles:collection-helpers in our Meteoris collection. Future explanation will be comming soon. ======== COMING SOON =========

3.6. Creating Server You can use reywood:publish-composite here. Future explanation coming soon. ======== COMING SOON =========

3.7. Using Meteoris Plugin For now You can refer to the below this Quick Start article.

====================================================================================

#1. INSTALLATION

meteor add meteoris:core

it will also installing it's dependencies, which are:

1.1. meteoris:flash

Meteoris Package to show Flash/Toast Error/Success in your bottom right screen.

enter image description here

how to use in your js file:

//set flash message example
Meteoris.Flash.set('success', 'Data Successfully added');
Meteoris.Flash.set('danger', 'Data Failed to be added');

how to use in your html file:

<!-- Simply place this code on your html view anywhere -->
{{> meteoris_flash}}

1.2. meteoris:form-validation

Meteoris package to validate form easily. This Meteoris.FormValidation extension depends on collection2 and simpleschema:

enter image description here

AccountType = new Mongo.Collection("accountType");

var schemas = new SimpleSchema({
    accountClassId: {
        type: String,
        label: "Kelas Akun",
    },    
});

AccountType.attachSchema(schemas);
  • how to use in your js helper:
    /* show error message on view */
    error: function(field) {
        return Meteoris.FormValidation.error(YourCollectionName, field);
    },
  • how to use in your html view:
       <div class="form-group {{#if error 'name'}}has-error{{/if}}">
            <label for="name" class="control-label">Kelas Akun *</label>
            <input type="text" id="name" value="{{name}}" placeholder="Kelas Akun" class="form-control" autofocus="true">
            <span class="help-block">{{error "name"}}</span>
        </div>

1.3. meteoris:formatter

  • this Meteoris.Formatter extension used for formatting anything like date, datetime, currency etc
  • this require lepozepo:accounting and momentjs:moment to works
  • how to use in your html view:

enter image description here

{{meteoris_formatter 'the function name' firstParam secondParam}}
  • available function name:
    - date (date)
    - dateTime (date)
    - elapsedTime (date)
    - currency (value)
    - combodate (date)
    - combodateEmpty (date)
  • example date formatting
{{meteoris_formatter 'date' getCurrDate}}
Template.someTheme.helpers({
	getCurrDate: function(){
		return new Date();
	}
});

1.4. meteoris:grid-view

  • this Meteoris.GridView extension used for sorting your table header ascending or descending.

enter image description here

  • how to use in your html view:
<th id="btnSortName" class="{{meteoris_gridViewSortClass 'name'}}">Name</th>
  • how to use in your js events:
    Template.accountTypeIndex.events = {
        /* sorting by parameter */
        'click #btnSortName': function(e) {
            Meteoris.GridView.sort('name');
        },
    }

#2. Install Meteoris Theme Admin (Not Required But It will better to be installed)

This current version of meteoris only have 1 theme which is called meteoris:theme-admin. This theme using popular Admin LTE for it's UI, Click here for more info about Admin LTE.

To install this theme, simply add meteor package:

meteor add meteoris:theme-admin

How to use

  1. You can do general setting of this theme by targetting this url /meteoris/theme-admin/setting

enter image description here

  1. You can easily hook sidebar in html file:

a. In your app client folder, create hook folder and inside it, add this template code. b. You can change everything such as loggedin user, global search, and menus inside the template as you wish

<!-- In your app client folder, create hook folder and inside it, add this template code. -->
<!-- You can change everything such as loggedin user, global search, and menus inside the template as you wish -->

<template name="meteoris_themeAdmin_hookSidebar">
    <!-- Left side column. contains the logo and sidebar -->
    <aside class="main-sidebar">
        <!-- sidebar: style can be found in sidebar.less -->
        <section class="sidebar">
            {{#if currentUser}}
            <!-- Sidebar user panel -->
            <div class="user-panel">
                <div class="pull-left image">
                    <img src="/images/user.png" class="img-circle" alt="User Image">
                </div>
                <div class="pull-left info">
                    <p>{{currentUser.profile.name}}</p>
                    <a href="#"><i class="fa fa-circle text-success"></i> Online</a>
                </div>
            </div>
            {{/if}}
            <!--search form--> 
            <form action="#" method="get" class="sidebar-form">
                <div class="input-group">
                    <input type="text" name="q" class="form-control" placeholder="Search...">
                    <span class="input-group-btn">
                        <button type="submit" name="search" id="search-btn" class="btn btn-flat"><i class="fa fa-search"></i></button>
                    </span>
                </div>
            </form>
            <!--/.search form--> 
            <!-- sidebar menu: : style can be found in sidebar.less -->
            <ul class="sidebar-menu">
                <li class="header">MAIN NAVIGATION</li>
                <li><a href="/"><i class="fa fa-home"></i> Home</a></li>
                <!--Uncomment this if you want to hide this menu using the power of meteoris:role-->
                <!--{{#if meteoris_roleUserIsInGroup "admin"}}-->
                <li class="header">ADMIN AREA</li>                
                <li class="treeview">
                    <a href="#">
                        <i class="fa fa-gears"></i>
                        <i class="fa fa-angle-left pull-right"></i>
                        <span>Setting</span>                                
                    </a>
                    <ul class="treeview-menu">                        
                        <li><a href="/meteoris/theme-admin/setting"><i class="fa fa-laptop"></i> Theme Admin Setting</a></li>                        
                        <li><a href="/meteoris/user"><i class="fa fa-users"></i> Users Management</a></li>                        
                        <li><a href="/meteoris/user/settings"><i class="fa fa-user"></i> User Settings</a></li>                                         
                        <li><a href="/meteoris/role"><i class="fa fa-flag-o"></i> Role Management</a></li>                                                
                    </ul>
                </li>
                <!--{{/if}}-->
            </ul>
        </section>
        <!-- /.sidebar -->
    </aside>        
</template>
  1. You can hook navbar too in html file: a. In your app client folder, create hook folder and inside it, add this template code. b. You can change everything such as notification, current logged in user, user profile menu etc inside the template as you wish
<template name="meteoris_themeAdmin_hookNavbar">
    <div class="navbar-custom-menu">
        <ul class="nav navbar-nav">
            {{#if currentUser}}
            <!-- User Account: style can be found in dropdown.less -->
            <li class="dropdown user user-menu">
                <a href="#" class="dropdown-toggle" data-toggle="dropdown">
                    <img src="/images/user.png" class="user-image" alt="User Image">
                    <span class="hidden-xs">{{currentUser.profile.name}}</span>
                </a>
                <ul class="dropdown-menu">
                    <!-- User image -->
                    <li class="user-header">
                        <img src="/images/user.png" class="img-circle" alt="User Image">
                        <p>
                            {{currentUser.profile.name}}
                        </p>
                    </li>
                    <!-- Menu Footer-->
                    <li class="user-footer">
                        <div class="pull-left">
                            <a href="#" class="btn btn-default btn-flat">Profile</a>
                        </div>
                        <div class="pull-right">
                            <a href="#" id="btnLogout" class="btn btn-default btn-flat">Logout</a>
                        </div>
                    </li>
                </ul>
            </li>
            {{else}}
            <li>
                <a href="/meteoris/user/login">Login</a>
            </li>
            {{/if}}
        </ul>
    </div>
</template>

c. add js file according to the template to get some event, and helper

var ctrl = new Meteoris.UserController();

Template.meteoris_themeAdmin_hookNavbar.events = {
    'click #btnLogout': function(){
        ctrl.logout();
    }
};

#3. Meteoris User (Not Required but it will be better to be installed)

  • NB: This package depends on Meteoris Theme Admin
  • The First Registered user will be assigned to admin group by default

You can use this main router:

'/meteoris/user', #to manage user as admin enter image description here

'/meteoris/user/login', #to logged in the user and '/meteoris/user/register', #to registering user enter image description here

'/meteoris/user/profile' #to updating current logged in user profile enter image description here

'/meteoris/user/settings', #to setting user oauth account enter image description here

#4. Install Meteoris Role (Not Required but it will be better to be installed)

enter image description here

How to use

1. Check whether current logged in user is in role or not in Collection/Server:

//you can use this code on collection-allow or on server
Meteoris.Role.userIsInRole(collection, action);

//example on collection:
MyCollection.allow({
    insert: function(userId, doc) {
        return Meteoris.Role.userIsInRole("my-collection", Meteoris.Role.POST);
    },
    update: function(userId, doc) {
        return Meteoris.Role.userIsInRole("my-collection", Meteoris.Role.PUT);
    },
    remove: function(userId, doc) {
        return Meteoris.Role.userIsInRole("my-collection", Meteoris.Role.DELETE);
    },
});

//example on router
var roleRoutes = FlowRouter.group({
    prefix: '/meteoris/role',
    name: 'meteoris_role',
    triggersEnter: [authenticating]
});

/* router level validation, only allow user with group "admin" to access this page */
function authenticating() {    
    if (!Meteoris.Role.userIsInRole("my-collection", Meteoris.Role.GET_ALL)){
        Meteoris.Flash.set("danger", "403 Unauthenticated");
        FlowRouter.go("/");
    }
}

2. Check whether current logged in user is in group or not in Collection/Server:

//you can use this code on collection-allow or on server
Meteoris.Role.userIsInGroup(groupName);

//example on collection:
MyCollection.allow({
    insert: function(userId, doc) {
        return Meteoris.Role.userIsInGroup("admin");
    },
    update: function(userId, doc) {
        return Meteoris.Role.userIsInGroup("admin");
    },
    remove: function(userId, doc) {
        return Meteoris.Role.userIsInGroup("admin");
    },
});

var roleRoutes = FlowRouter.group({
    prefix: '/meteoris/role',
    name: 'meteoris_role',
    triggersEnter: [authenticating]
});

/* router level validation, only allow user with group "admin" to access this page */
function authenticating() {    
    if (!Meteoris.Role.userIsInGroup("user")){
        Meteoris.Flash.set("danger", "403 Unauthenticated");
        FlowRouter.go("/");
    }
}

3. Check whether current logged in user is in role or not in Client template:

//you can use this code on client template html
{{#if meteoris_roleUserIsInRole "collectionName" "actionName"}}
<!-- Your logic here -->
{{/if}}

//example on client template html:
{{#if meteoris_roleUserIsInRole "my-collection" "GET_ALL"}}
<li><a href="/my-collection"><i class="fa fa-flag-o"></i> My Collection Menu</a></li>
{{/if}}

4. Check whether current logged in user is in group or not in Client template:

//you can use this code on client template html
{{#if meteoris_roleUserIsInGroup "groupName"}}
<!-- Your logic here -->
{{/if}}

//example on client template html:
{{#if meteoris_roleUserIsInGroup "admin"}}
<li><a href="/my-collection"><i class="fa fa-flag-o"></i> My Collection Menu</a></li>
{{/if}}

Author: Meteoris
Source Code: https://github.com/meteoris/meteoris 
License: 

#node #javascript #mvc #framework 

KambojaJS: New Meteoris, A MVC and Modular Framework for Meteor

Mixer: A MySQL Proxy Powered By Go

Mixer

Mixer is a MySQL proxy powered by Go which aims to supply a simple solution for MySQL sharding.

Features

  • Supports basic SQL statements (select, insert, update, replace, delete)
  • Supports transactions
  • Splits reads and writes (not fully tested)
  • MySQL HA
  • Basic SQL Routing
  • Supports prepared statement: COM_STMT_PREPARE, COM_STMT_EXECUTE, etc.

TODO

  • Some admin commands
  • Some show command support, i.e. show databases, etc.
  • Some select system variable, i.e. select @@version, etc.
  • Enhance routing rules
  • Monitor
  • SQL validation check
  • Statistics
  • Many other things ...

Install

cd $WORKSPACE
git clone git@github.com:siddontang/mixer.git src/github.com/siddontang/mixer

cd src/github.com/siddontang/mixer

./bootstrap.sh

. ./dev.env

make
make test

Keywords

proxy

A proxy is the bridge connecting clients and the real MySQL servers.

It acts as a MySQL server too, clients can communicate with it using the MySQL procotol.

node

Mixer uses nodes to represent the real remote MySQL servers. A node can have two MySQL servers:

  • master: main MySQL server, all write operations, read operations (if rw_split and slave are not set) will be executed here. All transactions will be executed here too.
  • slave: if rw_split is set, any select operations will be executed here. (can not set)

Notice:

  • You can use admin upnode or admin downnode commands to bring a specified MySQL server up or down.
  • If the master was down, you must use an admin command to bring it up manually.
  • You must set up MySQL replication for yourself, mixer does not do it.

schema

Schema likes MySQL database, if a client executes use db command, db must exist in the schema.

A schema contains one or more nodes. If a client use the specified schema, any command will be only routed to the node which belongs to the schema to be executed.

rule

You must set some rules for a schema to let the mixer decide how to route SQL statements to different nodes to be executed.

Mixer uses table + key to route. Duplicate rule for a table are not allowed.

When SQL needs to be routed, mixer does the following steps:

  • Parse SQL and find the table operated on
  • If there are no rule for the table, mixer use the default rule
  • If a rule exists, mixer tries to route it with the specified key

Rules have three types: default, hash and range.

A schema must have a default rule with only one node assigned.

For hash and range routing you can see the example below.

admin commands

Mixer suplies admin statement to administrate. The admin format is admin func(arg, ...) like select func(arg,...). Later we may add admin password for safe use.

Support admin functions now:

- admin upnode(node, serverype, addr);
- admin downnode(node, servertype);
- show proxy config;

Base Example

#start mixer
mixer-proxy -config=/etc/mixer.conf

#another shell
mysql -uroot -h127.0.0.1 -P4000 -p -Dmixer

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 158
Server version: 5.6.19 Homebrew

mysql> use mixer;
Database changed

mysql> delete from mixer_test_conn;
Query OK, 3 rows affected (0.04 sec)

mysql> insert into mixer_test_conn (id, str) values (1, "a");
Query OK, 1 row affected (0.00 sec)

mysql> insert into mixer_test_conn (id, str) values (2, "b");
Query OK, 1 row affected (0.00 sec)

mysql> select id, str from mixer_test_conn;
+----+------+
| id | str  |
+----+------+
|  1 | a    |
|  2 | b    |
+----+------+

Hash Sharding Example

schemas :
-
  db : mixer
  nodes: [node1, node2, node3]
  rules:
    default: node1
    shard:
      -   
        table: mixer_test_shard_hash
        key: id
        nodes: [node2, node3]
        type: hash

hash algorithm: value % len(nodes)

table: mixer_test_shard_hash

Node: node2, node3
node2 mysql: 127.0.0.1:3307
node3 mysql: 127.0.0.1:3308

mixer-proxy: 127.0.0.1:4000

proxy> mysql -uroot -h127.0.0.1 -P4000 -p -Dmixer
node2> mysql -uroot -h127.0.0.1 -P3307 -p -Dmixer
node3> mysql -uroot -h127.0.0.1 -P3307 -p -Dmixer

proxy> insert into mixer_test_shard_hash (id, str) values (0, "a");
node2> select str from mixer_test_shard_hash where id = 0;
+------+
| str  |
+------+
| a    |
+------+

proxy> insert into mixer_test_shard_hash (id, str) values (1, "b");
node3> select str from mixer_test_shard_hash where id = 1;
+------+
| str  |
+------+
| b    |
+------+

proxy> select str from mixer_test_shard_hash where id in (0, 1);
+------+
| str  |
+------+
| a    |
| b    |
+------+

proxy> select str from mixer_test_shard_hash where id = 0 or id = 1;
+------+
| str  |
+------+
| a    |
| b    |
+------+

proxy> select str from mixer_test_shard_hash where id = 0 and id = 1;
Empty set

Range Sharding Example

schemas :
-
  db : mixer
  nodes: [node1, node2, node3]
  rules:
    default: node1
    shard:
      -   
        table: mixer_test_shard_range
        key: id
        nodes: [node2, node3]
        range: -10000-
        type: range

range algorithm: node key start <= value < node key stop

table: mixer_test_shard_range

Node: node2, node3
node2 range: (-inf, 10000)
node3 range: [10000, +inf)
node2 mysql: 127.0.0.1:3307
node3 mysql: 127.0.0.1:3308

mixer-proxy: 127.0.0.1:4000

proxy> mysql -uroot -h127.0.0.1 -P4000 -p -Dmixer
node2> mysql -uroot -h127.0.0.1 -P3307 -p -Dmixer
node3> mysql -uroot -h127.0.0.1 -P3307 -p -Dmixer

proxy> insert into mixer_test_shard_range (id, str) values (0, "a");
node2> select str from mixer_test_shard_range where id = 0;
+------+
| str  |
+------+
| a    |
+------+

proxy> insert into mixer_test_shard_range (id, str) values (10000, "b");
node3> select str from mixer_test_shard_range where id = 10000;
+------+
| str  |
+------+
| b    |
+------+

proxy> select str from mixer_test_shard_range where id in (0, 10000);
+------+
| str  |
+------+
| a    |
| b    |
+------+

proxy> select str from mixer_test_shard_range where id = 0 or id = 10000;
+------+
| str  |
+------+
| a    |
| b    |
+------+

proxy> select str from mixer_test_shard_range where id = 0 and id = 10000;
Empty set

proxy> select str from mixer_test_shard_range where id > 100;
+------+
| str  |
+------+
| b    |
+------+

proxy> select str from mixer_test_shard_range where id < 100;
+------+
| str  |
+------+
| a    |
+------+

proxy> select str from mixer_test_shard_range where id >=0 and id < 100000;
+------+
| str  |
+------+
| a    |
| b    |
+------+

Limitations

Select

Join not supported, later only cross sharding not supported.

Subselects not supported, later only cross sharding not supported.

Cross sharding "group by" will not work ok only except the "group by" key is the routing key

Cross sharding "order by" only takes effect when the "order by" key exists as a select expression field

select id from t1 order by id is ok.

select str from t1 order by id is not ok, mixer does not known how to sort because it can not find proper data to compare with id

Limit should be used with "order by", otherwise you may receive incorrect results

Insert

  • "insert into select" not supported, later only cross sharding not supported.
  • Multi insert values to different nodes not supported
  • "insert on duplicate key update" can not set the routing key

Replace

  • Multi replace values to different nodes not supported

Update

  • Update can not set the routing key

Set

  • Set autocommit support
  • Set name charset support

Range Rule

  • Only int64 number range supported

Caveat

  • Mixer uses 2PC to handle write operations for multi nodes. You take the risk that data becomes corrupted if some nodes commit ok but others error. In that case, you must try to recover your data by yourself.
  • You must design your routing rule and write SQL carefully. (e.g. if your where condition contains no routing key, mixer will route the SQL to all nodes, maybe).

Why not vitess?

Vitess is very awesome, and I use some of its code like sqlparser. Why not use vitess directly? Maybe below:

  • Vitess is too huge for me, I need a simple proxy
  • Vitess uses an RPC protocol based on BSON, I want to use the MySQL protocol
  • Most likely, something has gone wrong in my head

Author: siddontang
Source Code: https://github.com/siddontang/mixer
License: View license

#go #golang #mysql 

Mixer: A MySQL Proxy Powered By Go